Skip to Content
Product Information
Author's profile photo Wouter Lemaire

Reactive programming with UI5 – ManagedObjectModel

There are already a few blogs out on Reactive programming with UI5. In most of these blogs, they use third party libraries like:

In this blog, I’ll show you how to achieve this with only UI5. No additional libraries ?

At UI5Con, Andreas Kunz announced the ManagedObjectModel. During his demo he showed how you can use this ManagedObjectModel to copy the properties and aggregations of a UI5 control to a new model. You can find the slides here:

https://www.slideshare.net/andreaskunz/ui5con-2018-news-from-control-development

The specific slide about the “ManagedObjectModel”

Here you can find the demo and the code behind:

Demo: https://rawgit.com/akudev/UI5con2018-ControlDevNews/master/www/ManagedObjectModel.html

Code: https://github.com/akudev/UI5con2018-ControlDevNews/blob/master/www/ManagedObjectModel.html

This new ManagedObjectModel opens another possibility than Andreas showed at UI5Con. It enables Reactive Programming with only using UI5 and no third-party libraries.

Let me show you how!

Basic Example

I created a UI5 app with all the basic components, like component, manifest, view and controller, and only on additional JavaScript object that I called “DemoState”. I use “State” because I will use it to keep the state of the app, like explained in the MobX blog.

This Object “DemoState” will extend from “ManagedObject” which has similar behavior as a UI5 Control but without the renderer function.  If you look at the objects that a UI5 control extends from, you’ll notice that it extends from “ManagedObject” (right in the middle). The “Element” and “Control” objects are adding UI related functionalities to the “ManagedObject”. The “ManagedObject” is responsible for the API of the control. This means that you can define properties, aggregations and events the same way as you do for UI5 Controls.

I have defined two properties in my “DemoState” object, one for a name and one for indicating if the name is valid. In this basic example, I’m going to overwrite the “generated” setter of the property name. Everytime that name changes, it will trigger this setter function. In the “setName”, I will check the incoming value for the name, update the name property and update the valid property depending on the incoming value. (FYI: the ManagedObject generates setters and getters for each property in case you do not create them)

sap.ui.define([
	"sap/ui/base/ManagedObject"
], function (ManagedObect) {
	"use strict";
	return ManagedObect.extend('be.wl.ManagedObjectDemo.state.DemoState', {
		metadata: {
			properties: {
				name: "string",
				nameIsValid: "boolean"
			},
			aggregations: {},
			events: {}
		},
		init: function () {},
		setName: function (value) {
			this.setProperty("name", value, true);
			if (value && value.length > 5) {
				this.setProperty("nameIsValid", true);
			} else {
				this.setProperty("nameIsValid", false);
			}
		}
	});
});

In the controller of the main view, I just create a new instance of “DemoState” put it in an instance of the “ManagedObjectModel” and set this model to the view.

sap.ui.define([
	"sap/ui/core/mvc/Controller",
	"../state/DemoState",
	"sap/ui/model/base/ManagedObjectModel"
], function (Controller,DemoState,ManagedObjectModel) {
	"use strict";
	return Controller.extend("be.wl.ManagedObjectDemo.controller.Main", {
		onInit: function () {
			this.getView().setModel(new ManagedObjectModel(new DemoState()));
		}
	});
});

In the view, I bind an input field to the “name” property and a read-only switch to the “nameIsValid” property. valueLiveUpdate is true so it will update directly.

<l:HorizontalLayout>
	<Input value="{/name}" valueLiveUpdate="true"/>
	<Switch type="AcceptReject" state="{/nameIsValid}" enabled="false"/>
</l:HorizontalLayout>

The full project structure looks like this:

If you run this and change the value in the input field, it will change the switch to green from the moment you have more than 5 characters.

See how it works:

Try it yourself:

https://plnkr.co/edit/Ib2IqZc2IjBZN7L2AvaI?p=preview

This was a very basic example and could also be achieved with binding expression without the additional “nameIsValid” property. But it shows you how you can react on a changed value without the need of an event => Reactive Programming.

Advanced example

The first example was very basic, let’s try to do something more advanced. This example will go further on the previous demo and it will use my service object like I have described in this blog:

https://blogs.sap.com/2018/09/17/ui5-odata-requests-with-promises/

I advise you to read that blog first. The following demo will also show the benefit of using the service object.

Let’s start by adding an aggregation to the “DemoState” to keep a list of Suppliers.

As you can see at the type of the suppliers, I had to create a “Supplier” object that extends from “ManagedObject”. I only use this object to define the structure of a “Supplier”:

In the “DemoState” I’ve changed the following in the function “setName”:

  • Decreased the length that defines if the name is valid or not
  • Clear the list of suppliers in case the name is not valid
  • Create a filter object for the name to use it for searching in Suppliers
    • Operator = contains
    • caseSensitive = false
  • Use the NorthwindService to get all the Suppliers that match the name value
    • Add the result of the call to the aggregation Suppliers of the DemoState

In the view, I moved the input field and switch to the subheader. In the content of the view, I’ve added a list to visualize the Suppliers:

You maybe didn’t notice, but we hadn’t to change the controller. We only need the setModel of the ManagedObjectModel that contains the DemoState. Everything else can now be done in the “DemoState”.

We’ll only use the controller in case we need to catch button presses.

In the end, it will work like this:

You can find the full project here:

https://github.com/lemaiwo/ManagedObjectDemo

 

Remark

You have to be aware that this “ManagedObjectModel” is currently not productive available in the latest version of SAPUI5. You’ll only find it in the nightly build:

https://openui5nightly.hana.ondemand.com/#/api/sap.ui.model.base.ManagedObjectModel

Even here it’s marked as “Expeprimental”:

Although you can’t find it in the documentation of https://ui5.sap.com/ and https://openui5.hana.ondemand.com/ , it’s already there but I won’t advice you to use it already for productive apps..

 

This will change the way you develop UI5 apps! 🙂

Assigned Tags

      7 Comments
      You must be Logged on to comment or reply to a post.
      Author's profile photo Michael Lichtinger
      Michael Lichtinger

      Great blog post Wouter Lemaire . Informative as always. 😉 Thanks for sharing.

      Author's profile photo Michelle Crapo
      Michelle Crapo

      There can never be enough of these blogs.   I love how you make it look so simple...  When to me it's not!

      Michelle

      Author's profile photo Helmut Tammen
      Helmut Tammen

      Great blog Wouter. I’m just using a self-build Redux-like architecture in one of my UI5 apps and experimenting with RxJS as well. Your blog comes in at the right time.

      Btw you can already do sort of reactive programing with JSONModels propertyChange event. Bind your UI to a JSONModel, implement the propertyChange event handlers and do whatever you want inside of them. The advantage compared to your solution is that you can easily access the JSON of the model and modify/enhance it as you need.

      The power of RxJS lies in its operators which allow you to do amazing things with incoming streams. 

      Author's profile photo Wouter Lemaire
      Wouter Lemaire
      Blog Post Author

      Hi Helmut,

      Indeed, JSONModel has a few features that allows you to do similar things. I use the JSONModel in a comparable way for building productive apps.

      The ManagedObjectModel is simply the better version of the JSON Model 🙂

      We should discuss this next time we meet 🙂 Interesting topic! I'm also very interested in your self-build Redux-like architecture!

      Kr, Wouter

      Author's profile photo Samuel Mok
      Samuel Mok

      I second that. I've been experimenting the managedobject model and my main gripe is accessing the JSON of the model easily.

      Author's profile photo Princis RAKOTOMANGA
      Princis RAKOTOMANGA

      Nice blog Wouter,

      Thanks for sharing.

      Since you work with ES6 modules, how about javascript proxy?

       

       

       

      Author's profile photo John Zhang
      John Zhang

      I second this.

       

      To implement a setter, one doesn't need ManagedObject. Instead, a POJO plus Proxy or Object.defineProperty will do.