Skip to Content
Author's profile photo Jakob Marius Kjær

Component Reuse – 4 ways of sharing data between the apps

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

Assigned Tags

      20 Comments
      You must be Logged on to comment or reply to a post.
      Author's profile photo Frank Liu
      Frank Liu

      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 .

      Author's profile photo Jérémy Coppey
      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.

      Author's profile photo Jakob Marius Kjær
      Jakob Marius Kjær
      Blog Post Author

      You should be able to simulate that in the run configuration on webide i believe.

      Author's profile photo se po
      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

       

       

       

      Author's profile photo Jakob Marius Kjær
      Jakob Marius Kjær
      Blog Post Author

      Hi Se,

       

      i think this answers your  question

       

       

      Author's profile photo se po
      se po

      Thanks :-)!

      Author's profile photo S G
      S G

      Hi Jakob,

      Nice blog!  Thanks Jakob!

      I am able to call the parent app models into child app successfully but not able to call the child app models into parent app. Is it possible to call models vice versa?

      Please help me on this requirement.

      Regards,

      S G

      Author's profile photo Jakob Marius Kjær
      Jakob Marius Kjær
      Blog Post Author

      Don't think that is possible  but just write your data into a model from the parent and you'll be fine.

      Author's profile photo S G
      S G

      Hi Jakob,

      Thank you for the reply.

      I am using 4th way(propagateModel) of sharing data between the bsp apps.

      As per your comment It may not be possible to share the models from child app to parent app.

      is there any other way to achieve this ? or can you please suggest who can help on this ?

      Regards,

      S G

      Author's profile photo Jakob Marius Kjær
      Jakob Marius Kjær
      Blog Post Author

      You could use the eventbus to achieve that result. Just remember to unsubscribe from your events upon exit.

      Author's profile photo S G
      S G

      Hi Jakob,

      Thank you, I am able to call the child BSP App Models into Parent BSP app and vice versa.

      and I doubt about eventbus,

      1. can we use this eventbus(model sharing between apps) in production level?
      2. Are there any disadvantages by using eventbus in the huge amount of data(more than 50,000 records) transfer between apps?

      Thanks in advance.

       

      Regards,

      SG

      Author's profile photo Jakob Marius Kjær
      Jakob Marius Kjær
      Blog Post Author

      Yeah i wouldn't recommend that.

      If you have that much data. I would create a model in the parent app and pass that on and update that in the child app.

      Author's profile photo Timothy Muchena
      Timothy Muchena

      Hi

      Thanks for the blog. Came to the rescue today.

      I see you are using private method  _getPropertiesToPropagate. Isn't that a bit risky? Is there a public method that can be used instead of a private method?

       

      Thank you

      Author's profile photo Jakob Marius Kjær
      Jakob Marius Kjær
      Blog Post Author

      Last time i checked that was the only way for us to get the propogated model unless you refer to the object itself. There is no public method.

      Author's profile photo Stefano Cataldo
      Stefano Cataldo

      Hi there,

      nice explanation … I try it myself and it worked fine ?

      I am using 4th way(propagateModel) of sharing data between the bsp apps.

      One question I still wonder about: In the on-Init of the child app, you put a time delay, because the component is  initiated before the component container. Can I get rid of this time delay?

      By setting the delay to 0, I would risk, that the funtion that.getOwnerComponent()._getPropertiesToPropagate(). will not work (the model is not there at this time). Right, so far?

      Is it possible to call the this function as soon as the model is available on the child app? 

      I try to found an explanation about when the model is propagate and how to react on that … but I don’t found ….

      Regards, Stefano

      Author's profile photo Jakob Marius Kjær
      Jakob Marius Kjær
      Blog Post Author

      Hi Stefano.

      You should be able to get rid of it. The model should be accessible via this.getOwnerComponent().getModel(<modelname >) bear in mind I wrote those blogs nearly two years ago. I should probably touch them up?

      Author's profile photo Stefano Cataldo
      Stefano Cataldo

      Thanks,  Jakob Marius Kjær.

      Author's profile photo Vicente Martinez
      Vicente Martinez

      Not trying to resurrect this or anything, but using onAfterRendering would solve the initialization issue. this.getOwnerComponent().getModel(<modelname >) wouldn't get you the model unless you leave the timeout there on onInit.

      Author's profile photo GOVARDAN RAJ SHAMANNA
      GOVARDAN RAJ SHAMANNA

      hi Jacob,

      Very Nice Blog,

      here am following the option of Event Bus,

      Am facing a problem, i.e. onselection of value in the valueHelpDialog, am publishing the event, and subscribing the same event at the OnInit Method of the Chid app.

      Even though am publishing the event only once, i.e. whenever we select value on value help dialog,

      but the subscribedevent at Oninit method is being executed Twice.

      Why is that being executed twice ???

       

      Regards

      Govardan

      Author's profile photo Ray Lv
      Ray Lv

      Hi Jacob,

      I like this blog, it's very useful.

      Thanks and Best Regards,

      Ray