cancel
Showing results for 
Search instead for 
Did you mean: 

Binding models together in sapui5 / mapping paths between models

Former Member
0 Kudos

Hi there,

is there a possibility to keep two models in sync or define a model which is just a view to some subset of information onto another model? Assume you have a model like this


var oModelA = new sap.ui.model.json.JSONModel({
    "dataInA": [
        { "name": "1st @ A" },
        { "name": "2nd @ A" }]});

and you want to have a model with a layout like this:


var oModelB = new sap.ui.model.json.JSONModel({
    "globalName": "?????"});

Can we link oModelB to oModelA such that


oModelB.getProperty("/globalName");

resolves to, e.g.,


oModelA.getProperty("/dataInA/0/name");

See this gist here.

You might argue: Why should we? Simply define the binding on the control such that it references "name" and use


oControl.bindElement("/dataInA/0").setModel(oModelA);

But I'm trying to write a control which consists of several sub-controls whose properties are named differently and which I want to address from the outside with only one property name -- and I thought doing it via an internal model would be the way.

Thanks,

M.

PS: To be more specific: I'm trying to write a control which yields a color field which on press yields a colorpicker which then changes the Color field -- pretty much exactly like the color picker in the DemoKit. But I would like to hide the two items (the picker and the color field indicating the selected color) within one control -- without writing all `bindProperty`, `setModel`, `unbindProperty`, `setProperty`, ... etc. myself and propagate them to the embedded controls. I was rather thinking about defining one model inside the control as CustomData and bind its properties from the outside and then use this control-local model to bind the Picker and the Color field to.

Accepted Solutions (0)

Answers (1)

Answers (1)

former_member182650
Contributor
0 Kudos

Hi Martin,

It could be possible to use global model, it has the possibility to merge different models:


var globalModel = new sap.ui.model.json.JSONModel();

sap.ui.getCore().setModel(globalModel);

var jsonModelCustomers = new sap.ui.model.json.JSONModel();        

jsonModelCustomers.loadData(YOUR_JSON_URL,{},false);

globalModel.setData({yourModel1Path: jsonModelCustomers.getData().customers}, true);

var jsonModelOrders = new sap.ui.model.json.JSONModel();        

jsonModelOrders.loadData(YOUR_JSON_URL,{},false);

globalModel.setData({yourModel2Path: jsonModelOrders.getData().orders}, true);

//In your global model are orders and customers

Kind regards!

Former Member
0 Kudos

Dear Angel,

thanks for your reply. However, I'm not trying to get two different models into one. I want one model to reference only a sub-part of the other. In your example: jsonModelCustomers contains various customers. Now I want a jsonModelSpecificCustomer to contain one of them but in a transparent way: When the jsonModelSpecificCustomer is changed the changes should be propagated back to the jsonModelCustomers and vice-versa: When the item in the global jsonModelCustomers is altered, the
jsonModelSpecificCustomer should be updated automatically.


Yours,

M.

former_member182650
Contributor
0 Kudos

Ok, in this case I don't know if there is an standard way to get this functionality. Let's investigate.

Kind regards

Former Member
0 Kudos

Hi Angel,

I think I found a solution myself, at least in parts:

I set up control which is not rendered but has two items in the CustomData Aggregation being bound to one model, respectively. Then you can get the corresponding PropertyBinding and attach an event handler to the change event and update the models cross-wise by hand, see again the gist. Here is the rough idea:


// set custom data referencing the sub parts of the models

var oCustomDataA = new sap.ui.core.CustomData({

key: "ModelA-data", value: "{A>" + sPathInModelA + "}"});

var oCustomDataB = new sap.ui.core.CustomData({

key: "ModelB-data", value: "{B>" + sPathInModelB + "}"});

// add to the connection element

oConnection.addCustomData(oCustomDataA);

oConnection.addCustomData(oCustomDataB);

// get the binding objects of the values of the custom data

var oPropertyBindingA = oCustomDataA.getBinding("value");

var oPropertyBindingB = oCustomDataB.getBinding("value");

// cross-connect their change events

oPropertyBindingA.attachChange(function(oChangeEvent) {

  oPropertyBindingB.setValue(

    oPropertyBindingA.getValue());

  // FIXME: also trigger a complete refresh of the model in

  // order to have controls updated which are refering to larger

  // parts of the model

});

// Likewise for the other ... you get the idea ...

This works if we consider the specific paths being bound. However, controls using a more global view onto the model are not informed that sub-elements have changed (This is what the FIXME is about, also see the gist).

HTH,

Martin

former_member189945
Contributor
0 Kudos

Hi Martin,

Did you find a solution for that FIXME part?

I think it could be solved by creating new sap.ui.model.Binding with the model instead of using the BindingInfo from an existing binding. BindingInfo notices changes on a given property/path but if you use sap.ui.model.Binding it should inform on all the changes. Though, using sap.ui.model.Binding is not exactly the "correct" way as it is an abstract base class.

More info on how Binding works here

-Kimmo

Former Member
0 Kudos

Hej Kimmo,

thanks for your reply. No, I did not solve them on a general level. In all cases I needed to use this I ended up explicitly refreshing the paths involved -- so everything was very hand-wired.

At the end, having several models sharing the same data also seems a bit un-MVC-ish. I just needed it as a wrapper around the data to match the control's needs on how the data should be put in the model. It is probably better to re-design the backend providing the data in order to match the frontend's needs more closely.

Best Regards,

M.

former_member189945
Contributor
0 Kudos

Hi Martin,

Thanks for sharing your thoughts.

Yes, definitely it's not the MVC way of doing things. Maybe some utility functions could benefit from it. E.g. generically listening to a model to get informed when it's internal state changed.


A while ago I experimented with generic undo/redo functionality for JSONModels. I ended up decorating the model with a utility class that kept track of all the changes. Another option I had in mind was having the Model inform about changes to itself. That way it could have been changed without using the decorator object but still keeping undo/redo functional.

-Kimmo