On April 16, 2018, Oracle JET version 5.0.0 has been released (Release Notes). Besides changes in the theming process and some oj-components, the update comes with a handy new ViewModel Lifecycle Listener. The listener is called propertyChanged() and does what the name already tells: It listens to changes of properties of composite components.

Building web applications with modularity is a great way to be able to reuse components and test them easily. Of course, components need to interact with each other and exchange data. This can be tricky if data is fetched asynchronously.

Let’s have a look on an example that demonstrates the issue. The application has a dashboard view and a dialog view called form-modal. form-modal is a composite component. The dialog is within the composite. By clicking a button in the dashboard, the dialog gets opened. Employees data from the dashboard is passed to the dialog.

dashboard.html

<oj-button on-oj-action="[[openModal]]">Open Modal</oj-button>
<form-modal id="formModal" persons="[[employees]]"></form-modal>

In the dashboard viewModel the employees are fetched asynchronously from the server.

self.employees = ko.observableArray();

fetch('https://jsonplaceholder.typicode.com/users')
    .then(response => response.json())
    .then(json => self.employees(json));

In the form-modal viewModel you can access the property „persons“ from the context parameter. However, in the moment of the initialization of the form-modal component, the employees are not available yet. And this is where propertyChanged comes into the game.

There’s been some lifecycle methods before:

  • activated
  • attached
  • connected
  • bindingsApplied
  • disconnected

These methods fire in different moments in the lifecycle of the component. The newly added propertyChanged() method fires once a property has been changed.

DialogComponentModel.prototype.propertyChanged = function(context){       
    if(context.property === 'persons') {
        this.persons(context.value);
    }
};

The change happens when in the dashboard viewModel the employees are successfully fetched.

Now one thing to mention is that parameter context carries only the value of the changed property. That’s why you need to check which property has changed with an if statement.

Why does propertyChanged make our lives easier?

Before v5.0.0 you would need a [property]Changed EventListener for every single property.

self.composite.addEventListener('personsChanged', event => {
    self.persons(event.detail.value);
})

Now with propertyChanged you have all change events in one method!

If you like to dive deeper into the topic, I recommend to read the the Lifecycle documentation. There is also a migration guide if you want to upgrade your v4 JET application to v5.