Question

I'm trying to get UI5 to change the row backgound based on the value of a field. This works after the initial load has been done and you scroll, but it doesn't work on the initial load.

This isn't working because the cell hasn't been added to its parent container as far as I can tell this.$().closest('tr') returns nothing. Upon scrolling the cell has been added to its parent, and then everything woks just fine.

<!DOCTYPE html>  
<html><head>  
    <meta http-equiv='X-UA-Compatible' content='IE=edge' />  
    <title>Bindign Rows</title>  

    <script id='sap-ui-bootstrap' 
        src='https://openui5.hana.ondemand.com/resources/sap-ui-core.js'  
        data-sap-ui-theme='sap_bluecrystal'  
        data-sap-ui-libs='sap.ui.commons,sap.ui.table'></script>   

    <script>  
       var data = [
           {sex: 'm', fname: 'XXX' , lname : 'YYYYY'},
           {sex: 'm', fname: 'XXX' , lname : 'YYYYY'},
           {sex: 'f', fname: 'XXX', lname : 'YYYYY'},
           {sex: 'f', fname: 'XXX', lname : 'YYYYY'} ,
           {sex: 'm', fname: 'XXX', lname : 'YYYYY'},
           {sex: 'f', fname: 'XXX', lname : 'YYYYY'}
       ];

       var oTable = new sap.ui.table.Table({visibleRowCount: 3});
       var oModel = new sap.ui.model.json.JSONModel();
       oModel.setData({modelData: data});
       oTable.setModel(oModel);

       var template1 = new sap.ui.commons.TextField().bindProperty("value", "sex", 
           function(sex){
              if(sex == "m" ){
                  //  !! the below parent can't be found.
                  this.$().closest("tr").css("background-color", "red");            
              }  else  if(sex == "f" )
              {  
                  this.$().closest("tr").css("background-color", "inherit");
              }
              return sex ;
            }
        );

        oTable.addColumn(new sap.ui.table.Column({ label: "Sex",
                                             template:  template1}));

    oTable.placeAt('content');  
    oTable.bindRows("/modelData");
</script>

</head>
<body class='sapUiBody'>
    <div id='content'></div>
</body>
</html>

What you'll see is that upon initial load all cells are grey.

When you scroll all cells with sex:M will get a red background. We'd love it if the red background would populate right from the first load.

enter image description here

JsBin link


Things we tried:

  • Supplying the template to the call to .bindRows('/data', template1), it seems that the type of template to supply to this call is a different one, but hardly documented on the SAP website.
  • Calling bindRows twice.
  • WORKAROUND: >>> doing the styling on a timer, works but is ugly and not stable enough.
  • I can't find a onParentChanged handler, onLoad or similar event that triggers after the data has been bound and I can't find an event akin to thd onDataBinding vs onRowCreated that I'm used to from my .NET background.
  • Just changing the style of the textbox itself works as is to be expected.
Was it helpful?

Solution

Better Solution

Combined addDelegate with the scroll handler on the vertical scrollbar, not ideal because they are both undocumented features

function updateRows(oEvent) {
    if (oEvent.type !== 'AfterRendering'){
      this.onvscroll(oEvent);
    }
    var rows = this.getVisibleRowCount();   //number of rows on tab
    var rowStart = this.getFirstVisibleRow();
    var ctx;
    for (var i=0; i<rows; i++){
       ctx = this.getContextByIndex(rowStart + i); //content
       this.getRows()[i].$().toggleClass("male",ctx?ctx.getObject().sex === 'm':false);
    }
};

oTable.addDelegate({ onAfterRendering : $.proxy(this.updateRows, oTable)});
oTable._oVSb.attachScroll(this.updateRows,oTable); 

see updated jsBin example

OTHER TIPS

WORKAROUND

Introducing a timer seems to work around the issue. I find it a very ugly solution and I'd prefer a better one, at least this seems to get us unstuck. Very much open to a better solution:

var template1 = new sap.ui.commons.TextField().bindProperty("value", "sex", 
  function(sex){
    var changeRow =  function(cell)
    {
      var row =  cell.$().closest("tr");
      if (row != undefined)
      {
        if(sex == "m" ){
          row.css("background-color", "red");            
        } 
        else
        {  
          row.css("background-color", "inherit");
        }
      }  
    };

    var row =  this.$().closest("tr");
    if (row.length != 0)
    {
      changeRow(this);
    }   
    else
    {
      // might need to increase the timeout. in the demo 150ms seems to be enough.
      window.setTimeout(changeRow, 150, this);
    }
    return sex ;
  }
);
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top