1
votes

I am creating a custom Control, and binding data to it. On click of button, I am changing the data in the Model, but the same is not reflected in DOM. Being new to SAP-UI5, I am not able to figure out the issue. Any help would be appreciated.

The code I am using:

    var aData = { person : [{firstName:"Bruce", lastName:"Wayne"}] };
    //set Model
    var oModel = new sap.ui.model.json.JSONModel(aData);
    sap.ui.getCore().setModel(oModel);

    //Declaring Renderer
    jQuery.sap.declare("PersonRenderer");
    PersonRenderer={render : function (oRm, oControl){
                    oRm.write("<ul style = 'margin:20px 50px;'");
                    oRm.writeControlData(oControl);
                    oRm.write(">");

                    var aItems = oControl.getModel().getData().persons;
                    for(var i=0,l=aItems.length; i<l; i++){
                        oRm.write("<li style='padding-top : 20px; font-size : 16px; border : 1px solid #cecece; color : #006699; font-weight : bold'> ");
                        oRm.write(aItems[i].firstName);
                        oRm.write("&nbsp;");
                        oRm.write(aItems[i].last);
                        oRm.write("</li>");
                    }
                    oRm.write("</ul");
                } }

     //Creating custom Element for binding. 
     //**Can we skip this and use existing controls like *TextField***???//

     sap.ui.core.Element.extend("PersonItems",{
        metadata : {
            properties : {
                "first" : {type : "string"},
                "last" : {type : "string"}
            }
        } });

      //Declaring custom control
      sap.ui.core.Control.extend("Person",{
        metadata : {
            properties : {
                aggregations : {
                    "items" : {type : "PersonItems", multiple : true, singularName : "Name_Singular"}
                },
                defaultAggregation : "items"
            },
            renderer :  PersonRenderer
        } });   

    //creating custom control
     var mPerson = new Person({
        items : {
            path : "/persons",
            template : new PersonItems({ first : "{firstName}", last : "{last}"})
            } 
        });

    //Creating a button
    var oBtn = new sap.ui.commons.Button('btn',{
        text : "Click",
        press : function(){
           //changed the model's property
            var model = sap.ui.getCore().getModel();
            model.setProperty("/persons/0/last",'Dog');
        }
    })

    mPerson.placeAt('master');
    oBtn.placeAt('master');

The Press function of button changes the model, but the view is not updated. How can i update the view on click of button and change of model.

Also, while using renderer function, PersonRenderer.js is created automatically. Directly placing the render function is not working. What is the reason? Is it because of aggregation binding? As in sapui5 examples, this works fine.

1
I see you're referencing a model inside your custom control (oControl.getModel().getData().persons), that is a no-no ;-) Always use the generated getters/setters, i.e. I believe oControl.getItems() for the items aggregation in your caseQualiture
The aggregation is falsely declared within the properties object. It should be a direct member of the metadata object in your Person control definition.Boghyon Hoffmann
The PersonRenderer is missing > at oRm.write("</ul");Boghyon Hoffmann
The data object contains the key named lastName but you're binding with {last}. It should be {lastName} - same as the key name. The path for the model.setProperty should be thus also /persons/0/lastNameBoghyon Hoffmann
The data object starts with the person key. However, the rest of the app uses persons.Boghyon Hoffmann

1 Answers

0
votes

In the object declaration at the start, you use "lastName" for the last name object attribute, but in the PersonItems template binding, you bind the control's property 'last' to the model property {last} - the model doesn't have a property named 'last', it has a property named 'lastName'. Change the binding to use property 'lastName'.