cancel
Showing results for 
Search instead for 
Did you mean: 

Conditional data binding?

Former Member
0 Kudos

Hi,

As part of my blog on sapui5 vs phonegap, I wanted to do data binding between phonegap exposed api and a sapui5 table view.

I looked at the contacts api, for which Phonegap returns the data in JSON format in a similar structure as the test case below.

var contacts = {

          modelData:

          [

                    {

                              displayName:"Dagfinn Parnas",

                              nickname:"Dagi",

                              phoneNumbers: [

                                        {type:"mobile", number:"9364xxxx"},

                                        {type:"home", number:"5165xxxx"},

                                        ],

                    },

                    {

                              displayName:"John Doe",

                              nickname:"Doh",

                              phoneNumbers: [

                                        {type:"mobile", number:"952xxxxx"},

                                        {type:"other", number:"5165xxxx"},

                                        ],

                    },

                    {

                              displayName:"Jane Doe",

                              nickname:"Doh",

                              phoneNumbers: [

                                        {type:"mobile", number:"12hxxxxx"},

                                        ],

                    },

          ]

};

As you can see, each contact has an array of phone numbers with varying type.

What I wanted to do is to bind the phoneNumbers which has type "mobile" to one sap.ui.table.Column, and those with type "home" to another one.

Unfortunately, I was not able to do this.

Is it possible to achieve it with sapui5 beta?

The closest I came is this test case.

It bind the first number to the first column and the second number to the second column.

<html>

<head>

  <meta http-equiv="X-UA-Compatible" content="IE=edge" />

  <title>sapui5 databinding</title>

                    <script src="/sapui5/resources/sap-ui-core.js"

                              type="text/javascript"

                              id="sap-ui-bootstrap"

                              data-sap-ui-libs="sap.ui.commons,sap.ui.table"

                              data-sap-ui-theme="sap_goldreflection">

                    </script>

<script>

jQuery.sap.log.setLevel(jQuery.sap.log.LogLevel['DEBUG']);

var contacts = {

          modelData:

          [

                    {

                              displayName:"Dagfinn Parnas",

                              nickname:"Dagi",

                              phoneNumbers: [

                                        {type:"mobile", number:"9364xxxx"},

                                        {type:"home", number:"5165xxxx"},

                                        ],

                    },

                    {

                              displayName:"John Doe",

                              nickname:"Doh",

                              phoneNumbers: [

                                        {type:"mobile", number:"952xxxxx"},

                                        {type:"other", number:"5165xxxx"},

                                        ],

                    },

                    {

                              displayName:"Jane Doe",

                              nickname:"Doh",

                              phoneNumbers: [

                                        {type:"mobile", number:"12hxxxxx"},

                                        ],

                    },

          ]

};

var oTable = new sap.ui.table.DataTable();

//two columns with simple binding

oTable.addColumn(new sap.ui.table.Column({

  label: new sap.ui.commons.Label({text: "Name1"}),

  template: new sap.ui.commons.TextView().bindProperty("text", "displayName"),

  sortProperty: "displayName"

}));

oTable.addColumn(new sap.ui.table.Column({

  label: new sap.ui.commons.Label({text: "Name2"}),

  template: new sap.ui.commons.TextView().bindProperty("text", "nickname"),

  sortProperty: "nickname",

}));

var oTVNumber1 = new sap.ui.commons.TextView();

oTVNumber1.bindProperty("text","phoneNumbers/0/number");

oTable.addColumn(new sap.ui.table.Column({

  label: new sap.ui.commons.Label({text: "Number1"}),

  template:oTVNumber1,

  sortProperty: "id",

}));

 

var oTVNumber2 = new sap.ui.commons.TextView();

oTVNumber2.bindProperty("text","phoneNumbers/1/number");

oTable.addColumn(new sap.ui.table.Column({

  label: new sap.ui.commons.Label({text: "Number2"}),

  template:oTVNumber2,

  sortProperty: "id",

}));

var oItemTemplate2 = new sap.ui.core.ListItem();

oItemTemplate2.bindProperty("text", "type").bindProperty("additionalText", "number");

var oListTemplate = new sap.ui.commons.ListBox("myLb3", {displaySecondaryValues:true, height:"200px"});

oListTemplate.bindAggregation("items", "phoneNumbers", oItemTemplate2);

oTable.addColumn(new sap.ui.table.Column({

  label: new sap.ui.commons.Label({text: "Phone"}),

  //template: new sap.ui.commons.ComboBox().bindItems("phoneNumbers", oListItemTemplate),

  template:oListTemplate,

  sortProperty: "id",

}));

//create model

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

//set model with a new root element

oModel.setData(contacts);

//bind model to table

oTable.setModel(oModel);

//bind table to the root element in the model

oTable.bindRows("modelData");

oTable.placeAt("dataTable");

//list test 1

var oLB = new sap.ui.commons.ListBox("myLb", {displaySecondaryValues:true, height:"200px"});

oLB.setModel(oModel);

oLB.bindContext("/modelData/1");

var oItemTemplate = new sap.ui.core.ListItem();

oItemTemplate.bindProperty("text", "type").bindProperty("additionalText", "number");

oLB.bindAggregation("items", "phoneNumbers", oItemTemplate);

oLB.placeAt("list1");

//TextView test

</script>

</head>

<body class="sapUiBody">

  <h1>sapui5 databinding</h1>

  <div id="dataTable"></div>

  <div id="singleproperty"></div>

  <div id="list1"></div>

  <div id="list2"></div>

</body>

</html>

Accepted Solutions (1)

Accepted Solutions (1)

UweFetzer_se38
Active Contributor
0 Kudos

Hi Dagfinn,

I don't think binding directly to the table is possible, but this seams to be more a Javascript problem.

You may try to extend the model data on the fly, something like this (haven't tested yet, but you see, what I mean):

for data in modelData {

     for phoneNumber in phoneNumbers{

          data[phoneNumber["type"]] = phoneNumber["number"];

     };

};

And then you should be able to bind the new fields modelData.mobile, modelData.home and mobileData.others to the columns. This is more a workaround than a solution, I know.

Best regards

Former Member
0 Kudos

Thanks Uwe,

Yes, flattening the json or java object would be the workaround in this case.

And your method is quite elegant I must say.

However, the json structure returned by phonegap is often used in services and it should not be necessary to flatten it. Flattening it will also make it very hard to have a two-way binding with the model.

My suggestion would be to introduce the possibility of a computed property that is bindable.

Knockoutjs framework has a computed observable that serves this purpose

"That’s where computed observables come in - these are functions that are dependent on one or more other observables, and will automatically update whenever any of these dependencies change."

http://knockoutjs.com/documentation/computedObservables.html

Here is an example

//this is a standard property

this.lastName = ko.observable("Bertington");

//this is a computed once

this.mobile = ko.computed(function(){

      for phoneNumber in this.phoneNumbers{ 

          if(phoneNumber.type=='mobile'){

               return phoneNumber.number;

     }

     return null;

}

I would love to sapui5 also get this feature and hope someone from the sapui5 team can comment on that.

Regards

Dagfinn

pmuessig
Advisor
Advisor
0 Kudos

Hi Dagfinn,

did you notice the 3rd parameter of the bindProperty function? It allows you to e.g. pass a formatter function for the binding which can be used to intercept a value and afterwards adopt this value and return something computed as you called it.

Here is a sample for the property binding of the "home" phone number column:

            var oTVNumber1 = new sap.ui.commons.TextView(); 

            oTVNumber1.bindProperty("text", "phoneNumbers", function(aValue) {

                var sNumber = "";

                if (aValue) {

                    jQuery.each(aValue, function(iIndex, oValue) {

                        if (oValue.type === "home") {

                            sNumber = oValue.number;

                            return false; // break

                        }

                    });

                }

                return sNumber;

            }); 

           

            oTable.addColumn(new sap.ui.table.Column({ 

                label: new sap.ui.commons.Label({text: "Home"}), 

                template:oTVNumber1

            })); 

As value of the formatter function you receive the object/array containing the phone numbers.

Is this what you was looking for?

Best regards,

Peter

qmacro
Developer Advocate
Developer Advocate
0 Kudos

Great discussion!

I took the liberty of cleaning up the sample code and adding the dynamic formatter function that Peter pointed out. I investigated making this sort of thing a little bit more generic, see what you think.

Gist here: https://gist.github.com/2788164

Cheers

dj

Former Member
0 Kudos

Hello,

I've tested you code, but the table is not getting filled like it should look at the screenshot below:

I'm running the code on my local test server for netweaver cloud.

Can you please help me?

Code I used:

http://pastie.org/5406392

qmacro
Developer Advocate
Developer Advocate
0 Kudos

Hi Vincent

Interesting find. I'm guessing you're using the latest SAPUI5 version (1.8.4) which was recently made available.

There's a subtle difference between the binding path between the table and the JSON model. What worked prior to 1.8.4 was a relative path at the root, i.e.

oTable.bindRows("modelData");

but in fact what is required now is an absolute path, i.e.

oTable.bindRows("/modelData");

You can see the difference if you run your code (http://pastie.org/5406392) in Chrome against a 1.8.4 release, and then in the developer tools JavaScript console re-bind by entering:

oTable.bindRows("/modelData");

and you should see the data appear in the table.

Note also that even though it still works, DataTable is now deprecated in 1.8.4.

cheers

dj

qmacro
Developer Advocate
Developer Advocate
0 Kudos

Actually also just found this comment on another post here which confirms this:

http://scn.sap.com/community/developer-center/front-end/blog/2012/10/15/consume-netweaver-gateway-se...

Former Member
0 Kudos

Hey DJ,

It seems to work like a charm!

Thanks a lot for this quick fix!

Kind regards,

Vincent

Former Member
0 Kudos

Hi DJ,

Great solutions! Thanks so much for posting it. Now I have a similar case where I need to create a select list with different values for each row. My data looks like this:

var questions = {"ques" : [

                                        {

                                             "Q" : Description ID1,

                                             "Opt" : [{"Options":Option1},

                                                            {"Options":Option2},

                                                            {"Options":Option3},

                                                            {"Options":Option4}]

                                           },

                                             {

                                             "Q" : Description ID2,

                                             "Opt" : [{"Options":Option1},

                                                            {"Options":Option2},

                                                            {"Options":Option3},

                                                            {"Options":Option4}]

                                           },

                                             {

                                             "Q" : Description ID3,

                                             "Opt" : [{"Options":Option1},

                                                            {"Options":Option2},

                                                            {"Options":Option3},

                                                            {"Options":Option4}]

                                           },

                                             {

                                             "Q" : Description ID4,

                                             "Opt" : [{"Options":Option1},

                                                            {"Options":Option2},

                                                            {"Options":Option3},

                                                            {"Options":Option4}]

                                           },

                                             {

                                             "Q" : Description ID5,

                                             "Opt" : [{"Options":Option1},

                                                            {"Options":Option2},

                                                            {"Options":Option3},

                                                            {"Options":Option4}]

                                           }

                                   ]

                         };

Thanks so much any tips!

Cheers,

Ron

Answers (1)

Answers (1)

Former Member
0 Kudos

Hi guys,

I want to pass a single value from Page1 to Page2 in a SAPUI5 Mobile APP. Then on page 2 I want to use this value for some logic implementation. Please guide me how can i pass a single value between 2 pages and then how to access/use this value on the second page.

Thanks and best regards.

Fahad

Former Member
0 Kudos

Hi Fahad,

U can use local storage to store the variable.

Cheers

Vinay