Create a Type From Code

When you want to use your own type (for example, a type class written in JavaScript or a typescript class) with a variable in Visual Builder, you can create a type from code to create an instance of that type class. Types from code, called InstanceFactory types, can be created by importing your type definition to declaratively plug in any Oracle JET type class or a custom type class, then using it with a category of variable known as an InstanceFactory variable.

InstanceFactory types and variables let you use your own type class (say, the myapp/MyTypeFromCode JavaScript class) as a type with Visual Builder variables without having to re-implement a new type (Javascript class) that uses or extends the VB Extended Type framework. You'll only need to provide a typescript definition file (*.d.ts) or a typescript file (*.ts) that defines your type's details. Visual Builder will parse your type definition, generate a JSON representation that is compatible with existing type schema, and create an InstanceFactory type, which you can then assign to an InstanceFactory variable (vb/InstanceFactory). The InstanceFactory variable uses the InstanceFactory type and additionally the list of constructor arguments declared by the type to define its constructor parameters (constructorParams).

The InstanceFactory variable that uses an InstanceFactory type creates immutable instances of the type class. When a page loads, the InstanceFactory variable creates the first instance of the type (using the configured constructor parameters). It also creates a new instance of the type class whenever its constructor parameters change. You can use the Assign Variables action or the Reset Variables action to update constructor parameters.

You can also use the Call Variable action to call methods on the variable instance (see Add a Call Variable Action).

To create a type from code:

  1. Select your application (or fragment) in the Navigator.
  2. Click the Types tab to open the Types editor.
  3. Click + Type and select From Code in the menu. This option is available only at the app (or fragment) level, so make sure you've selected the correct node in the Navigator.
  4. Enter the type name using namespaces (for example, myapp/MyTypeFromCode) and click Create. Namespaces separated by a slash (/) help organize the types.

    An InstanceFactory type is created, with its default icon set to oj-ux-ico-software. A default display label is also generated based on your values, as shown here in the Properties pane:



  5. If you want, configure the type's properties to use a custom display label and a display icon of your choice. In our example, let's set the display label to MyTypeFromCode and the display icon to oj-ux-ico-phone.
  6. Drag and drop (or click Upload type definition to provide) a typescript (.ts) or typescript definition (.d.ts) file that specifies the type's details:


    Visual Builder converts your type definition to a JSON representation, then saves the JSON file under resources/typedefs/.

After you've created a type from code, you can create a variable for this InstanceFactory type, just as you would for any other type. For example, here's a myVar variable assigned to the MyTypeFromCode type:

However, because an InstanceFactory type includes a constructor, initializing InstanceFactory type variables is not the same as other variables. It requires parameters to be mapped to the constructor. To do this, click Assign in the variable's Properties pane, then map the constructor parameters.

The shape for the constructor parameters comes from your type definition file. Here's an example type and variable declaration as shown on the JSON tab:

  "types": {
    "myapp/MyTypeFromCode": {
      "label": "MyTypeFromCode",
      "constructorType": "vb/InstanceFactory<myapp/MyTypeFromCode>",
      "iconClass": "oj-ux-ico-phone",
      "typedef": "resources/typedefs/myapp/MyTypeFromCode.json"
    }
  },
  "variables": {
    "myVar": {
      "type": "myapp/MyTypeFromCode",
      "constructorParams": [
        "Book Giver",              <<<<< this is title
        {                          <<<<< this is author
          "firstName": "Lois",
          "lastName": "Lowry"
        },
        49.99                     <<<<<<< this is price
      ]
    }

Note:

To make the JavaScript implementation for types like myapp/MyTypeFromCode available at runtime, make sure the path to your implementation is correctly mapped in requireJS, for example:
"requirejs": {
    "paths": {
      "myapp": "resources/js/myapp"
    }
  },
One InstanceFactory variable can reference another InstanceFactory variable. In this example, the incidentsView variable references incidentsSDP, another InstanceFactory variable:
"incidentsSDP": {
  "type": "vb/ServiceDataProvider2",
  "constructorParams": [
    {
      "endpoint": "demo-data-service/getIncidents",
      "keyAttributes": "id",
      "itemsPath": "result",
      "uriParameters": "{{ $variables.technicianURIParams }}"
    }
  ]
},
"incidentsView": {
  "type": "ojs/ojlistdataproviderview",
  "constructorParams": [
    "{{ $page.variables.incidentsSDP.instance }}",
    {
      "sortCriteria": [
        {
          "attribute": "priority",
          "direction": "ascending"
        }
      ]
    }
  ]
}

Any time the incidentsSDP variable changes (that is, a new instance is created), the incidentsView variable re-creates a new instance of ojs/ojlistdataproviderview. This also means that components bound to either variable are notified of the change.