Skip to Content

This is the second part of my blog series around component reuse. These are the contents of the blog series

  1. Demystifying the art of component reuse in SAPUI5
  2. Component Reuse – 4 ways of sharing data between the apps
  3. Simplifying the component reuse to work both on premise and in cloud and using the manifest.json

 

In the last blog I explained how we can incorporate a separate app inside a component container to be used in a parent application. This is really useful in a modular architecture.

However while it is great, it starts becoming really cool, when we can actually use that to work on the same data. An example could be a custom app as a search help, which can then retrieve a resultset and pass the selected option back to the parent app.

Currently I see 5 different ways of doing this and I will explain and show all four in this blog.

  1. Using the Window object
  2. Using the eventBus
  3. Using a core model
  4. Using a propogated model

I am fully aware that there is do’s and don’ts on the above options, but this blog is just to show you the options.

Alright down to business!

First example is quite simple, You can store objects in the window object, which is a representation of the open window on the browser. You can simply store variables here similar to storing in the “this” object by writing window.<your variable> = <the value>. While it is really simple to use, it is generally discouraged as any function in will have access to the variable and can change it.

In my example I create my text in the component.js file of the parent app.

window.windowText = “Window”;

In the onInit function of my view controller in the child app, i declare a local json model and fetch the text and set it into the model

onInit: function(){
    var windowText = window.windowText,
	jsonModel = new JSONModel({
		            windowText : windowText
			   });
				
	this.getView().setModel(jsonModel, "myModel");
},

In the view itself, it is bound like this

<Text text="{myModel>/windowText}"/>

Remember to deploy to see your changes 😉

A drawback of this, is that if you change the variable stored in the window object, it doesn’t change the binding in the child app, leaving you with a rather static option.

The next option is to use the EventBus which was used in the early days of SAPUI5 for navigation, but obviously routing has taken over here. But it is still used occasionally for handling events.

The Eventbus works on a subsribe and publish basis. You need to declare the channel and the event you want to subscribe to and then you use the same for when you want to publish data in the event.

In the onInit function of the child controller we add the following code to handle the event

sap.ui.getCore().getEventBus().subscribe("exchange", 
"data", function(channel, event, oEventData){
					that.getView().byId("EventBusText").setText(oEventData);
				}, this);

 

And in the view itself we create a Text control with the id EventBusText

<Text id="EventBusText"/>

I have added an input field in the parent app and in the change event of that field we use the following code to publish an event

sap.ui.getCore().getEventBus().publish("exchange", 
"data", oEvent.getParameter("newValue"));

That is it for the second example. This allows you to share data between the apps. So when you change in the parent app, you see it in the child.

The drawback here is that you need to unsubscribe to the events or at least only use the method subscribeOnce in the eventbus.

You can obviously also use a more model based approach and use a jsonModel that you store in the core of SAPUI5. This model can then be address in the child app by accessing the core.

We use the existing jsonModel used in the parent app. The following code adds the data to the json model and then then save that into the core.

			var oModel = this.getModel(),
				oJsonData = {
					MyNumber: 100000.1234,
					MyText: "Hello World",
					coreText: "Core",
					propagateModelText: "propagateModelText"
				};
				
			oModel.setData(oJsonData);
		
			
			sap.ui.getCore().setModel(oModel, "coreModel");

Now in the child apps onInit controller again we add the following

	var oData = sap.ui.getCore().getModel("coreModel").getData();
				
				//Now merge the two objects and store it again to the child apps model
				var newData = Object.assign(jsonModel.getData(), oData);
				jsonModel.setData(newData);

In the view we add the Text to see the new change.

<Text text="{myModel>/coreText}"/>

Drawback here is now that your model is stored in the core and can again be accessed via other apps and you need to handle that accordingly.

Last and best option is to use the propogatedModel when we declare the componentContainer. As the documentation says

you want to share data with the inner component, you can use property propagateModel on the ComponentContainer to forward models and binding contexts to the inner component.

So basically we can forward our models from the parent app into the child app.

<core:ComponentContainer width="100%" 
						name="bourneMyChildApp" 
						component="bourneMyChildApp"
						propagateModel="true"
			    		/>

Back to the onInit controller again in the child app and add the following to the code. I’ve added the timeout here, because the component is initiated before the component container and because of the small footprint, the propogatedmodel isn’t added when we load this. But with the timeout that is fixed.

var that = this;
setTimeout(function(){
//Get the propogated model from the component. It is called undefined as we 
// havent named the model in the parentApp
	var oModel = that.getOwnerComponent()._getPropertiesToPropagate().oModels.undefined;
//Create a new model in the view called parentModel
        that.getView().setModel(oModel, "parentModel");
}, 1000)

This is the end result that you should get

When you use the propogated model it is important to have a look at the lifecycle of the component container. Read the Using and Nesting Components

Reason for this is that once you initiate your child app inside the container and you then relaunch the app, then your child app is already initiated and will cause you problems. More on that in my next blog.

My next blog will be about how we can leverage the manifest.json file a bit more and thereby remove the jquery dependencies in the parent app component.js file that we wrote in the first blog. Also I will show a little snippet on how you can handle component reuse once, that then will work both on premise and in the cloud.

You can find the source files here.

As always please reach out to me on twitter on uxkjaer

To report this post you need to login first.

5 Comments

You must be Logged on to comment or reply to a post.

  1. Former Member

    Nice blog!  Thanks Jakob!

    We found another way to share data that you can set model for the instance of child component in parent app and use the ModelContextChange event to define the process of reaction within child app .

    (0) 
  2. Jérémy Coppey

    Nice Blog!,

    Do you have a clue how I can start the child app with start up parameters, the app has been created for Fiori Launchpad use with Semantic Navigation with parameters.

    What we want to do is use the apps outside the Fiori launchpad and thus not make use of semantic navigation with parameters. The problem is we “can’t” change the code of the child component so using the propogated model is no option for the moment.

     

    Thanks.

    (0) 
  3. se po

    Hi Jakob,

    Thanks for this nice blog-series! It helped me figure out quicker some essential aspects of component reuse.

    Nonetheless there is still one point that I can’t tell for sure how would work within a component re-use scenario… maybe you already faced this issue.

    Let’s say I have a child-app that has some routes defined (E.g.: master-detail app). My parent-app will also use some routes. Do you know how will the routing happen in this case? Any chance problems might arise due to both apps using the routing functionality?

    My guess is that routing inside the child-app will not be visible…

    Thanks!
    Se Po

     

     

     

    (0) 

Leave a Reply