Thursday, November 8, 2018

Managing Persisted State for Oracle JET Web Component Variable with Writeback Property

Starting from JET 6.0.0 Composite Components (CCA) are renamed to be Web Components (I like this new name more, it sounds more simple to me). In today post I will talk about Web Component writeback property and importance of it.

All variables (observable or not) defined inside Web Component will be reset when navigating away and navigating back to the module where Web Component is included. This means you can't store any values inside Web Component, because these values will be lost during navigation. Each time when we navigate back to module, all Web Components used inside that model will be reloaded, this means JS script for Web Component will be reloaded and variables will be re-executed loosing previous values. This behaviour is specific to Web Component only, values for variables created in the owning module will not be reset.

If you want to keep Web Component variable value, you will need to store variable state outside of Web Component. This can be achieved using Web Component property with writeback support.

Let's see how Web Component behaves on runtime. Source code is available on my GitHub repo.

Here I got basic Web Component included into dashboard module:


Web Component doesn't implement anything except JET switcher. Once switcher state is changed, variable is updated in JS script:


Variable which holds switcher state in Web Component:


Web Component is reloaded each time we navigate away and come back to the module - this means variables will be reset. This is how looks like - imagine we open module for the first time, switcher position is OFF:


Change it to be ON:


Navigate to any other module and come back - you will see that switcher is reset back to default OFF state, this means variable was reset (otherwise we should see ON state):


If you want to keep variable state, then it should be maintained outside of Web Component. To achieve this, create Web Component property to hold variable value, make sure set this property with writeback support:


For debugging purposes, add logging into Web Component, this will help to see when it will be reloaded:


Switcher variable must be initialized from Web Component property. Very first time it will be empty, but as soon as user will changed switcher state -  next time when Web Component is reloaded, it will assign correct value which was selected before:


When switcher state is changed, we need to handle this event and make sure that Web Component property is updated with new value:


Writeback property must be assigned with observable variable which is created in the module. Variable reference must be writable with {{}} brackets:


Once value will be changed inside Web Component, this change will be propagated up to observable variable defined in the module. Next time when we navigate away and come back to the module - we will pass recent value to the Web Component:


This is how it works now. Load module, change switcher state (see in the log -  Web Component was loaded once):


Navigate to any other module:


Come back to the module, where Web Component is included. See in the log - Web Component is reloaded, but switcher variable value is not lost, because it was saved to module observable variable through Web Component writeback property:

4 comments:

Anirban Mukherjee said...

Hi Andrejus,

Is there any configuration approach to reset all observables when we re-enter a module? One way I can think of is to make use of the connected or disconnected methods and manually reset all observables to their original states. But for a large module with a large number of such variables, this is quite a big task. I was wondering if there is something equivalent to isolated scope of an ADF task-flow.

Regards.

Andrej Baranovskij said...

Hi,

In JET you need to reset variables manually. If you want declarative development in JET, similar to ADF - then need to use VBCS.

Andrejus

Anirban Mukherjee said...

Andrejus,

An observation: I see that writeback is required only for primitive data types. If we pass an object (e.g. { rows: 'single' }) as a CCA property and we change the object from inside the CCA on the context (e.g. context.properties.selection.rows = 'multiple') then we don't need a writeback true for that CCA property. The object on the parent module gets updated even without writeback. This probably makes sense since primitives are passed by value, and objects are passed by reference.

Let me know your thoughts on this.

Best Regards.
Anirban

Andrej Baranovskij said...

Yes, this makes sense.

Andrejus