Technical Articles relating to Oracle Development Tools and Frameworks

  • JET
    April 18, 2018

JET 5.0.0 - Notes for JET Custom Component Authors

Duncan Mills

As is traditional with new JET version I like to review what that release will mean for those of us building our own JET Custom Components (CCA) and this 5.0 release is no exception, in fact it's a pretty exciting1 release for component writers 

Unlike the past couple of point releases, JET 5.0.0 is, of course, a major release and as such we've got the opportunity to make some significant changes, but don't worry, your existing code will still function as before, (but watch out because some patterns have become deprecated). 

Changes to Component Registration

I'll get this one out of the way first as it should (hopefully) effect no-one, but if it does then it's important. If you take a peek at your loader.js script for any components that you write you'll (hopefully) see something like the following register function call:

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

You'll notice that the view, viewModel and metadata attributes are all set to an object with an inline attribute that then has the relevant values set.
Now what you might not realise (unless you've been through my blog series very carefully) is that as well as using this inline attribute, you could also use a promise attribute to pass the view etc. The idea here is that these resources could be delivered asynchronously if you really needed it.

Well we've been building custom components for a couple of years now, and no-one has ever seriously used this capability, so we've decided that we probably don't really need it after all! Therefore the ability to use promise here has been removed. This will both simplify the framework code used to register components, and deliver a significant bonus to you which I'll discuss in the next section

So when you create new components for use in JET 5.0 and above you can use the slightly simplified structure for your loader where you no longer need to mention "inline":

oj.Composite.register('some-component-name', {
      view: view, 

Simplifying Working With Properties

Several changes here, all again to make your life easier and to re-emphasise the old approaches still work as well!

Goodbye "props", hello "properties"

I'm sure that you are used by now to reading your component properties via the context.props.then() promise callback - usually, but not always, called from your component constructor. Did you ever wonder why properties are delivered in this weird asynchronous way?  It certainly can cause problems for developers who are not familiar with working with promises.  Well the reason that you got your properties via a promise was, you've guessed it, the fact that the component registration might be done with promises. Now that we've removed that option, there is no need to deliver the property values in this way. Now you will be able to access properties and slot counts immediately from the constructor/lifecycle context via two new attributes context.properties and context.slotCounts. No need to use a then() function, just reference the property you need directly. These will also be available in your view via $properties and $slotCounts respectively. The old promise based context variables (props and slotNodeCounts) are now depreciated and should be phased out. 

Property Change Listeners

The next super convenient change relating to properties, is a new way to deal with property changes once the component is up and running. You often need to keep an eye on a property value just in case the consumer of the component has bound it to an observable and that observable changes. So a very common pattern for component developers is to create a whole set of <propertyName>Changed listeners on the component during the attached() phase of the lifecycle to handle this. 

We appreciate that this is a bit of a pain to have to do for something that is so common, so JET 5.0 introduces a new lifecycle callback that does all the hard work for you!

Now, if you are interested in listening for property changes within your component, all you have to do is to implement a propertyChanged2 method. This function is called every time that a component property is updated and it is passed a context object that mimics the propertyChanged event object that you'll be used to parsing, with the addition of a property attribute that names the property that has been mutated. So now listening to property changes just needs you to implement that function and not have to muck around with attaching event listener functions to the component.

When Can Properties be set?

The final result of the removal of promises from the registration process is that you are now able to set properties on the custom component at any time and don't have to wait until it's fully initialised (or as we say upgraded) before doing so. This is unlikely to be something that you'd notice but does catch folks out from time to time if they are dynamically building up a UI.

Metadata Changes

With this release the we have one small change to the component.json metadata definition which you can take advantage of. This is the new component level dependencies attribute which is intended to replace the existing compositeDependencies attribute which is now deprecated.  We have made this change in order to convey the information that your components might depend on more that just other composite components in the future (watch this space!)

Accessing Component Metadata

Another side effect of the removal of promises from the registration process is that this allows us to provide more direct access to the component metadata at runtime. In versions of JET prior to JET 5 you would use the oj.Composite.getMetadata() method, passing the name of the component and would receive a promise back, which, when resolved, would supply the metadata object.  For 5.0.0 we have introduced a new, simpler API oj.Composite.getComponentMetadata() which returns the metadata object directly without a promise getting in the way. The old API continues to function of course, but is deprecated and should be swapped out for this new one.

Helping you to Help Yourself

I've mentioned in past articles about how you have to be careful about not-redefining the standard HTMLElement attributes in your component.json (these are attributes such as id, title and style).  In JET 4.0 we tightened up the framework which resulted in a lot of folks running into a mysterious "_BRIDGE" error when trying to use their components in JET 4.n.  The good news is that we now have a friendly error message on the console to tell you exactly what you have done wrong:

Error registering composite <some-component>. Redefined global HTML element attribute 'id' in metadata.

Hopefully this will speed up your error diagnosis!

Another similar help for you is that we now apply a marker class to components that have failed during startup. You may be familiar with the fact that we apply the oj-complete marker style to a component when it's ready for action. Well we now also cover the opposite case, if something has gone wrong, we apply an oj-incomplete marker.  This should help you identify what might be causing problems in your pages.

These changes together will hopefully make the whole process of building components that little bit simpler and less error prone. Have fun!

And Finally

Sometimes deprecated really means that! With this release, a bunch of features that we deprecated in JET 3 and 4 have really been removed. This seems to have surprised come people who though that we are just kidding - well we're not... The one that seems to have caught most people out is the removed of the variant of the automatically created property change event with a hyphen in it.  Up until now we have omitted two events for each property change the "new" <propName>Changed and the older (and deprecated) <propName>-changed.  With this release we're back down to just one, so check your code!

As usual, you can (and should) check out the Release Notes for the full list of changes. For reference here's the stuff we've removed:

  • oj.Composite.defaults method
  • dispose ViewModel lifecycle method: Use the detached method instead.
  • [propertyName]-Changed events: Listen for the [propertyName]Changed events instead.
  • pending and ready events: Use the oj.BusyContext to determine when composites are ready instead.

1For some definition of exciting

2Pay attention if your component already has such a function name internally it would now be called when-ever a property changes at the framework level!

Be the first to comment

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