Adding calculated fields
Glossary Item Box
Introduction
A calculated field is a page control element, whose value is generated based on the status and values in other elements on this page.
In bpm’online, calculated fields are based on the bpm’online client mechanism, which uses subscriptions to change events in view model schema attributes. For any attribute, you can set a configuration object and specify object schema column names. If the values in these columns change, the value of the calculated column will be updated. You can also specify the handler method for this event.
The general sequence of adding a calculated field is as follows:
- Add a column for storing the values of the calculated field to the page object schema.
- In the page view model, set up attribute dependencies by specifying column names from which the attribute depends and the handler name.
- Add the implementation of the handler method to the method collection of the view model.
- Set up the display of the calculated field in the diff property of the view model.
Setting up dependencies of the calculated field
In the attributes view model property, add an attribute for which the dependency is configured.
Declare a dependencies property, which is an array of configuration objects, each of which contains the following properties:
- Сolumns – an array of columns, whose values determine the value of the current column.
- methodName – handler method name.
If the value of at least one of these columns changes in the view model, the event handler method (whose name is specified in the methodName property) will be called.
The handler method implementation must be added to the collection of the view methods.
Case description
Add [Payment balance] to display the balance between order amount and payment amount on the order edit page.
NOTE
You can add fields to the edit page manually or using the section wizard. Learn more about adding fields to edit pages in the “Adding a new field to the edit page” article.
Source code
You can download the package with case implementation using the following link.
Case implementation algorithm
1. Create a replacing object
Select the custom package on the [Schemas] tab an click the [Replacing object] in the [Add] menu. Select the [Order] object as the parent object (Fig. 1).
Fig. 1. Properties of the [Order] replacing object
Add a new [Payment balance] column of the [Currency] type to the replacing object (Fig. 2).
Fig. 2. Adding a custom column to the replacing object
Publish the object.
2. Create a replacing client module for the order edit page
A replacing client module must be created and [Order Edit Page] (OrderPageV2) must be specified as the parent object in it (Fig. 3). Creating a replacing page is covered in the “Creating a custom client module schema” article.
Fig. 3. Properties of the replacing edit page
3. Set up the display of the [Payment balance] field
Describe the configuration object with the required parameters in the diff property of the view model. Page schema source code is available below
4. Add the UsrBalance attribute to the view model schema
Add the UsrBalance attribute to the collection of the attributes property in the source code of the page view model. Specify dependency from the [Amount] and [PaymentAmount] columns, as well as the calculateBalance() handler method (which will be calculating the value of the [UsrBalance] column) in the configuration object of the UsrBalance attribute.
5. Add the needed methods in the methods collection of the view model
In the methods collection of the view model, add the calculateBalance() handler method that will handle the editing of the [Amount] and [PaymentAmount] columns. This method is used in the UsrBalance attribute.
ATTENTION
Make sure you take into consideration the type of data in the handler method that need to be returned in the calculation field as a result. For example, the [Decimal (0.01)] data type assumes a number with two decimals. Before recording the result in the object field, convert it via the toFixed() function. The example code in this case could look as follows:
// The calculation of difference between the [Amount] and [PaymentAmount] column values.
var result = amount - paymentAmount;
// The calculation result is assigned as a value to the [UsrBalance] column.
this.set("UsrBalance", result.toFixed(2));
Override the onEntityInitialized() base virtual method. The onEntityInitialized() method is triggered after the edit page object schema is initialized. Calling the calculateBalance() handler method to this method will ensure the calculation of the amount to be paid at the moment the order page opens and not only when the dependency columns are edited.
The complete source code of the module is available below:
define("OrderPageV2", [], function() { return { // Edit page object schema name. entitySchemaName: "Order", details: /**SCHEMA_DETAILS*/{}/**SCHEMA_DETAILS*/, // The attributes property of the view model. attributes: { // Name of the view model attribute. "UsrBalance": { // Data type of the view model column. dataValueType: Terrasoft.DataValueType.FLOAT, // Array of configuration objects that determines [UsrBalance] column dependencies. dependencies: [ { // The value in the [UsrBalance] column depends on the [Amount] // and [PaymentAmount] columns. columns: ["Amount", "PaymentAmount"], // Handler method, which is called on modifying the value of the on of the columns: [Amount] // and [PaymentAmount]. methodName: "calculateBalance" } ] } }, // Collection of the edit page view model methods. methods: { // Overriding the base Terrasoft.BasePageV2.onEntityInitialized method, which // is triggerd after the edit page object schema has been initialized. onEntityInitialized: function() { // Method parent implementation is called. this.callParent(arguments); // Calling the handler method, which calculates the value in the [UsrBalance] column. this.calculateBalance(); }, // Handler method that calculates the value in the [UsrBalance] column. calculateBalance: function() { // Checking whether the [Amount] and [PaymentAmount] columns are initialized // when the edit page is opened. If not, then zero values are set for them. var amount = this.get("Amount"); if (!amount) { amount = 0; } var paymentAmount = this.get("PaymentAmount"); if (!paymentAmount) { paymentAmount = 0; } // Calculating the margin between the values in the [Amount] and [PaymentAmount] columns. var result = amount - paymentAmount; // The calculation result is set as the value in the [UsrBalance] column. this.set("UsrBalance", result); } }, // Visual display of the [UsrBalance] column on the edit page. diff: /**SCHEMA_DIFF*/[ { "operation": "insert", "parentName": "Header", "propertyName": "items", "name": "UsrBalance", "values": { "bindTo": "UsrBalance", "layout": {"column": 12, "row": 2, "colSpan": 12} } } ]/**SCHEMA_DIFF*/ }; });
After saving the schema, updating the web page and clearing the cache, a new [Payment balance] will appear on the order page. The value in this field will be calculated based on the values in the [Total] and [Payment amount] fields (Fig. 4).
Fig. 4. Case result demonstration