InstanceFactory Types

vb/InstanceFactory

With an InstanceFactory type, authors can declaratively plug in any JET type or a custom type, and use it with a special Visual Builder variable (instance factory variable). The InstanceFactory type:

  • Supports creating immutable, or re-creatable (type) classes.
  • Many constructs in JET are immutable classes that are then assigned to component properties. As a framework, Visual Builder facilitates the (re)creation of these classes, and reassignment when the configuration of these classes change .
  • The vb/InstanceFactory variable takes in the JS (type) class, as well as the parameters to the constructor. When bound, this variable provides an 'instance' of the class (along with the 'constructorParams').
  • When the constructor parameters change, the InstanceFactory variable will automatically create a new instance of the class.
  • Like regular variables, a VB 'valueChanged' event is fired when an InstanceFactory variable changes. The event payload will have the old and new values containing the two properties constructorParams and instance.
  • The 'constructorParams' of the variable alone will be serialized and persisted, not the instance. If the constructorParams includes a property that references another InstanceFactory variable, then that variable needs to be marked 'persisted', if author wants to persist the full tree. It's preferable that authors always update the 'constructorParams', so the instance is created automatically. If the instance is updated separately from constructorParams, the persisted state may not accurately reflect the correct state.

Associate a type with a variable to create an instance of that type

This example shows how you can do this.

Code Description
1  "variables": {
2    "customersADP": {
3      "type" : "ojs/ojarraydataprovider",
4    "constructorParams": []
5    }
6  },
7  "types": {
8    "ojs/ojarraydataprovider": {
9      ...
10     "constructorType": "vb/InstanceFactory"
11   }
12  }
  • Line 3: use the JET array data provider type ojs/ojarraydataprovider. This module is automatically loaded when the variable is created, because a require mapping for ojs already exists.
    • you must use a '/' in its name
  • Line 8: types declaration for ojs/ojarraydataprovider
  • Line 10: indicates that instance of JET ADP is created using a vb/InstanceFactory.
    • An author can use the short convention, in which case the type name is assumed to be the require JS module, Or use the longer convention "vb/InstanceFactory<ojs/ojarraydataprovider>", if the typename is different than the actual require path.

Specify an array of params using the 'constructorParams' property

In this example, a JET ADP takes a data array as its first param and an options Object as its second param.

Code Description
1  "customersADP": {
2    "type" : "ojs/ojarraydataprovider",
3    "constructorParams": [
4      "{{ $page.variables.customersData }}",
5      {
6        "keyAttributes": "id",
7        "textFilterAttributes": [
8          "lastName",
9          "firstName"
10       ]
11     }
12   ]
13 }
  • Line 4: customersData is the data array
  • Line 5: options object

Create an instance of the type, when the variable 'customersADP' is created

The variable has two properties that are stored in redux.

instance

This holds the constructed ADP instance.

A component that wants an ADP instance can use it this way.

<oj-select-single id="ss11"
 value="{{ $variables.customerId }}"
 
 data="[[ $variables.customersADP.instance ]]"
 
 item-text='[[ $page.functions.getItemText ]]'>
</oj-select-single>

constructorParams

  • the array of params passed to the constructor of the type
  • the constructorParams can be used in EL expressions as well for readonly expressions
  • $variables.customersADP.constructorParams

Note:

The properties defined on the instance can be mutated directly, and will be reflected on the instance stored in redux.

The methods available on the instance can be called directly.

The properties and methods supported on the instance are assumed to be declared by the type author using typescript or at design-time. This information is not relevant for runtime purposes.

To change the 'constructorParams'

Variable properties can be changed in several ways.

Using assignVariables action

For an InstanceFactory variable that is defined like this:

"incidentsList": {
  "type": "vb/ServiceDataProvider2",
  "constructorParams": [
    {
      "endpoint": "demo-data-service/getIncidents",
      "keyAttributes": "id",
      "itemsPath": "result",
      "uriParameters": "{{ $variables[\"technicianURIParams\"] }}"
    }
  ]
},
"incidentsListView": {
  "type": "ojs/ojlistdataproviderview",
  "constructorParams": [
    "{{ $page.variables.incidentsList.instance }}", // SDP2
    {
      "sortCriteria": [
        {
          "attribute": "priority",
          "direction": "ascending"
        }
      ]
    }
  ]
}

The assignVariablesAction below adds a filterCriterion property on the constructorParams of the JET ListDataProviderView variable. This assignment will cause the variable to create a new instance based on the new values.

"setFilterCriterion": {
  "module": "vb/action/builtin/assignVariablesAction",
  "parameters": {
    "$page.variables.incidentsListView.constructorParams[1]": {
      "source": {
        "op": "$eq",
        "attribute": "status",
        "value": "accepted"
      },
      "mapping": {
        "$target.filterCriterion": {
          "source": "$source",
          "reset": "empty"
        }
      },
      "reset": "none"
    }
  }
}

Using resetVariables action

For an InstanceFactory variables that is defined like above, the resetVariablesAction looks like below to reset the view variable.

"resetVariables": {
  "module": "vb/action/builtin/resetVariablesAction",
  "parameters": {
    "variables": [
      "$page.variables.incidentsListView"
    ]
  }
}

Using component writeback via EL bindings

Note:

This option is not supported.

Call methods on the instance using an action

You can use 'callVariableMethodAction' to call any method, including async methods. It's important to remember that because actions in a chain are intrinsically synchronous, a method that returns a Promise waits for the Promise to resolve before executing the next action.

"callGetCapabilityChain": {
  "root": "getCapabilityOnLDPV",
  "actions": {
    "getCapabilityOnLDPV": {
      "module": "vb/action/builtin/callVariableMethodAction",
      "parameters": {
        "variable": "$page.variables.incidentsListView",
        "method": "getCapability",
        "params": [
          "sort"
        ]
      }
    }
  }
}

Update the instance and constructorParams together

You can use the assignVariablesAction and a built-in function to update the instance and constructorParams together.

In the following example, Line 6 uses a built-in utils called 'assignmentUtils' that provides an assignValue method. This allows authors to provide both the updated instance, and the associated constructorParams.

1  "assignInstanceAndCPToListViewVar": {
2    "module": "vb/action/builtin/assignVariablesAction",
3    "description": "update variable instance and constructorParams declaratively",
4    "parameters": {
5      "$page.variables.incidentsListView": {
6        "module": "{{ $application.builtinUtils.assignmentUtils }}",
7        "functionName": "assignValue",
8        "params": [
9          {
10           "instance": "{{ $chain.results.setFilterCriterion_priorityLow.instance }}",
11           "constructorParams": "{{ $chain.results.setFilterCriterion_priorityLow.constructorParams }}"
12         }
13       ]
14     }
15   }
16 }