X

Technical Articles relating to Oracle Development Tools and Frameworks

JET Custom Component Authors Prepare for JET 7.0.0!

Duncan Mills
Architect

With JET 7.0.0 due, it's a great time to review any Custom Web Components, that you may have created in the past, for deprecated features.  This is particularly important for Visual Builder Cloud Services customers who may have created and embedded custom components into their deployed applications. These could cease to function in JET 7.0.0 if they are using features due for removal.

Here's a quick review of the deprecated features that you might still be be using and of course what to do about each. The good news is that you can make all these changes today in your JET 6.n or Visual Builder 19.1.3 code bases and be ready. I have blogged about some of these in past articles but this is a good opportunity to provide a roll-up checklist for you. 

Changes to the Loader.js

There have been three changes to the component loader file over the last 3 major releases of JET:

  1. Deprecation of the use of promises in component registration
  2. Change to obtaining the Composite object
  3. Deprecation of the passing of a CSS to the component.registration

Let's look at each of those in turn:

Promises in Component Registration

In JET 5.0.0 we removed the unused capability to use promises in the component registration process. You will have not used this capability, however, your component registration code might still have a passing reference that needs to be corrected. This is indicated by the use of the inline attribute in the descriptor object that is passed to the Composite register function, for example:

Before
oj.Composite.register('my-component', { 
    view: {inline: view}, 
    viewModel: {inline: viewModel}, 
    metadata: {inline: JSON.parse(metadata)}
}

Notice how each of the descriptor attributes (view, viewModel and metadata) are passed a sub-object with an inline attribute. This can now all be simplified:

After
Composite.register('my-component', { 
    view: view, 
    viewModel:viewModel, 
    metadata:JSON.parse(metadata)
}

In the new simplified version we just pass the view etc. directly as the attributes of the descriptor, so it's a simple change to make to the code.

A related change to discuss at the same time is to do with the actual value passed as the view attribute of the register descriptor in earlier versions it was possible to pass a DOM fragment or an array as the view.  This attribute is now restricted to passing a string value representing the HTML template for the component.

Getting the Composite object 

In JET 6.0.0 we deprecated the use of the oj.Composite for obtaining the Composite object to use for registration in favour of the more modular approach of obtaining the object directly from ojs/ojcomposite. In an older custom component you might have a define block that uses the ojs/ojcore module to obtain the oj object which was then used to obtain the Composite object -  looking a little like this:

Before

define(['ojs/ojcore', 
        'text!./my-component-view.html', 
        './my-component-viewModel', 
        'text!./component.json',
        'css!./my-component-styles',
        'ojs/ojcomposite'],
  function(oj, view, viewModel, metadata) {
    oj.Composite.register('my-component', { 
    ...
    }

Note the import of ojs/ojcore in the define as the constructor parameter oj and the use of that in the oj.Composite.register() call. The updated code for this same function now is to explicitly use the ojs/ojcomposite module directly instead to gain access to the register function, removing the need to reference ojcore at all:

After

define(['ojs/ojcomposite', 
        'text!./my-component-view.html', 
        './my-component-viewModel', 
        'text!./component.json',
        'css!./my-component-styles'],
  function(Composite, view, viewModel, metadata) {
    Composite.register('my-component', { 
    ...
    }

In the amended version you can see that the reference to the ojcore module is removed and the ojs/ojcomposite import is now passed to the constructor parameter Composite. The component registration function now simply makes the Composite.register() call without routing through oj.

Note that this change applies throughout your custom component coding, not just the Composite.register() function, so take the opportunity to refactor any oj.* references to use the more modular alternatives whilst going through your components. 

Passing CSS as part of the Component Register Call

This was a feature that was deprecated back in JET 4, but again, take this as an opportunity to clean up any code that is still using it. In very early versions of JET custom components you could pass a reference to a style sheet using the css attribute of the definition object passed to the Composite.register function. So you might have something like this.

Before

oj.Composite.register('my-component', { 
    view: {inline: view}, 
    viewModel: {inline: viewModel}, 
    metadata: {inline: JSON.parse(metadata),
    css: {inline: styles}}
}

That css reference is no longer supported, instead you use the css RequireJS plugin in your define block to achieve the same end.  Therefore the amended version will look like:

After
define(['ojs/ojcomposite', 
        'text!./my-component-view.html', 
        './my-component-viewModel', 
        'text!./component.json',
        'css!./my-component-styles'],
    Composite.register('my-component', { 
      view: view, 
      viewModel:viewModel, 
      metadata:JSON.parse(metadata)
  }

Notice the css!./my-component-styles entry in the define import array which does the CSS loading for us. (Note that I've also made the other amendments outlined in this article as well as dealing with the css loading)

Changes to the Main Component Lifecycle

Attached / Detached

Back in JET 4.2.0 we made the component lifecycle more predictable with the introduction of the connected and disconnected lifecycle methods. These replaced the older attached and detached methods, at this point you should have already amended any usages accordingly, however, take the opportunity to check.

ViewModel - Constructor v's Instance

In JET 5.0.0 we restricted the bootstrapping components to only allow a constructor function to be passed as the viewModel (via the Composite.register() function). In earlier versions we had also allowed you to pass an object instance to the register() at which point we would call the initialize() lifecycle method. Now that this capability has been removed please scan your code for use of the initialize callback, and if it turns out that you are still using this old style initialization then amend your code to pass a constructor function to Composite.register(). If you are unclear how to do this then just use the ojet command line tool to generate a new component (using the ojet create component ... command) and follow the pattern that it uses for the generated viewModel.js file.  

Other Miscellaneous Changes

Accessing Properties 

With the removal of promise support from the component registration process we where able to simplify the access to properties within your component viewModel.  Early component code would usually have code like this in the constructor where a .then() function would be used to wait for the asynchronous delivery of component properties via a promise:

Before

function ComponentModel(context) {
  var self = this;
  self.composite = context.element;
  context.props.then(function (propertyMap) {
    //Store a reference to the properties for any later use
    self.properties = propertyMap;
    //Parse your component properties here
    ...
  });
}

This can all be simplified now as the properties are delivered synchronously on the context:

After
function ComponentModel(context) {
  var self = this;
  self.composite = context.element;
  self.properties = context.properties;
  //Parse your component properties here
  ...
}

Notice the use of context.properties rather than context.props to access the properties. This is also reflected in any use of properties in your view html where you can use the $properties root rather than $props to access them.

Accessing Slot Information

In a pattern just like that of property access above, access to slot information, specifically the node count) has moved from being a promise based API to one of immediate access from the constructor context via the context.slotCounts parameter rather than the promise based context.slotNodeCounts

These are the significant deprecations that will effect your code so do take the opportunity to clean up your code now so that you are ready for JET 7. Also remember to read the release notes with every JET release and proactively react to deprecations as they are announced.

Join the discussion

Comments ( 2 )
Please enter your name.Please provide a valid email address.Please enter a comment.CAPTCHA challenge response provided was incorrect. Please try again.