cancel
Showing results for 
Search instead for 
Did you mean: 

sap.ui table change color of specific rows

0 Kudos

Consider a table with 50 records. visibleRowCount is set to 15, so when table is loaded with data there are only 15 records displayed. I need to change color of some specific rows based on values (lets say when a cell has value "Total"). Assume, "Total" appears in rows 2,4 8. I can change the color of these rows. getRows() works well before I start scrolling a table down,The problem is that getRows() method returns only # of visible rows in the table. Therefore, when I scroll table down the rows 2, 4 ,8 are colored permanently. In this case the logic that it should depend on value "Total" doesn't work. Is thre any chance I can fix this issue? Thanks!

Accepted Solutions (0)

Answers (18)

Answers (18)

former_member182862
Active Contributor

IMO, this is a very trick thing to do because the table control does not render the rows when we scroll, instead it replace the content on the content accordingly. This is a trick to handle this by extending one of the controls. In my example, I use sap.m.Text.

https://jsbin.com/curuhab/edit?html,js,output

former_member185280
Active Contributor

In the past I have taken advantage of aggregation binding factory functions - https://sapui5.hana.ondemand.com/#/topic/335848ac1174435c901baaa55f6d7819

What I was doing was more involved with dynamic controls so it may not be the best solution for this.

View:

<table:Table rows="{/Rows}" visibleRowCount="10">
   <table:columns>
      <table:Column>
         <table:template>
            <HBox alignItems="Center"
                 displayInline="true"
                 items="{
                    path: 'value/0',
                    templateShareable:true,
                    factory: '.resultColumnFactory'
            }">
            </HBox>
         </table:template>
      </table:Column>
   </table:columns>
</table:Table>

Controller:

resultColumnFactory: function (sId,oContext) {

var color = "";
var path = oContext.getPath().split("/");
var Row = this.getView().getModel().getProperty("/" + path[1] + "/" + path[2]);
            var oText = new Text(sId, { text: Row.value });

            if(Row.value == "Good"){
                color = "green";
            }

            oText.addEventDelegate({
                "onAfterRendering": function () {
                    this.$()
                        .closest( "tr" )
                        .css( "background-color", color );
                }
            }, oText);

            return oText;
  }
leonikussmaul
Product and Topic Expert
Product and Topic Expert
0 Kudos

Hi,

Although this question is a bit older, a quick workaround for getRows() that helped me still missing in this thread.

Simply bind the visibleRowCount property of the table to the model that has the table data stored and calculate the length using expression binding. This way avoids any complicated JS code and handles the calculation directly in the XML view.

visibleRowCount="{= ${tablemodel>/rows}.length }"

In this example i have stored the data for the rows inside the rows property of my JSON Model "tablemodel". Now getRows() returns all the rows and in the controller you can get the desired rows of your table to apply custom style classes from your CSS file, i.e.;

controller: this.getView().byId("sTableId").getRows()[1].addStyleClass("myStyleClass")

css stylesheet: .myStyleClass { color: #dc0d0e!important; }

While this worked for my use case and certainly would for some others, it might not be the best approach for a large dataset.

Hope this helps.

0 Kudos

Hi Sergey,

I have faced the same issue and I have tried all the possible solutions provided. Finally I have got one working solution which satisfies the scenario. There is an Event in sap.ui.table "firstVisibleRowChanged" which will get triggered when the first row of the table get changed. This will possibly happen when we scroll the table. So under this function you can use addStyleClass() method to dynamically apply the css to the rows.

firstVisibleRowChanged: function() {

console.log('scrolled');

}

Reference: https://jsbin.com/buhekugexi/edit?html,js,output

0 Kudos

today I had the same problem.... after some research, I found a workarounding way how to highlight ui.table rows.

1.) I define a css class like

.testing { background-color:green!important; }

2.) (read to the end now) in XML view I define customData to e.g. my Text element:

<uit:columns>
<uit:Column >
<Label text="ID"/>
<uit:template>
<Text text="{x>x}" wrapping="false">
<customData>
<core:CustomData key="highlightrow" value="{x>x}" writeToDom="true" />
</customData>
</Text>

3.) in my controller, I will do following in any event like model attachRequestCompleted or onAfterRendering:

$("span[data-highlightrow='true']").parent().parent().parent().addClass("testing");

With this, I got my row (tr) colored

also have a look at this (not the requested, but maybe still not known for some people)... cant post the link due sap domain only restriction... so look in the sapui5 documentation samples at Grid Tables -> row highlights

0 Kudos

Hi Sergey Kochetkov,

1. You can use formatter with a dynamic CSS class. So you can write your logic with respect to the row total in your formatter.js link

2. If you want to get entire rows for table visible or not visible, you can use below code or read the rows from data model.

var totalRows = this.getView().byId("oTable").getAggregation("rows").length;

3. Like Blas _ suggested you can use Core:CustomData with css field

tr."your_custom_class"[data-mydata="yes"] { color: black !important; background-color: yellow !important}  

Regards,

Sai Santhosh

0 Kudos

Hi Sai Santhosh, thanks for the alternatives.

1. Can you explain a little this? the class adds dynamically in the formatter?

2. The problem's sergeyzh is that is not possible get all the rows in the table ui with getRows(), only return visible rows. The getAggregation("rows") not work, only return visible rows, .... the same problem.

3. True, i used CustomData and my problem was that i have un input and the CSS change XD, I used div[data-mydata="si"] input {} and work it.

Do you know why this error in console ” CustomData with key mydata should be written to HTML of Element sap.m.Input#application-Test-url-component—object–__clone116 but the value is not a string. ” ??I have a String in value CustomData in the model

Thank you, Sai.

Regards

santhu_gowdaz
Active Contributor
0 Kudos

=== not ==

class="{= ${modelo>propiedad}==='si'?'colorClass':''}

0 Kudos

Thanks santhu.gowdaz

With === doesn't work either. The background of Text control doesn't color. Do you tried this?

Regards

0 Kudos

Thanks Sergey for the explication, i understand it. The solution make it work!!! 🙂

My problem is that i have a sap.m.Input, not Text ... and not found. Do you have any idea please??

Regards

<t:Column width="5rem" sortProperty="myColumn" filterProperty="myColumn">
     <t:multiLabels>
	<Label text=""/>
	<Label text="nombre"/>
     </t:multiLabels>
     <t:template>
        <Input maxLength="2" value="{ path: 'modelo>propiedad' }">
           <customData>
             <core:CustomData key="mydata" value="{modelo>propiedad}" writeToDom="true"></core:CustomData>
           </customData>
        </Input>
     </template>
<t:Column>

0 Kudos
If someone has the same problem. Looking the Html tags in the view i saw the error ... Wiith Input the DOM element that’s rendered is a DIV, not SPAN, so the css changes and work it!
div[data-mydata="si"] input { 
     background-color:#f9f9c2 !important; font-weight: bold; 
     border: 3px solid red !important;
}

Someone knows why this error in console ” CustomData with key mydata should be written to HTML of Element sap.m.Input#application-Test-url-component—object–__clone116 but the value is not a string. ” ??

I have a String in value CustomData in the model: <core:CustomData key=”mydata” value=”{val}” writeToDom=”true”></core:CustomData>

It works well but appears this error.

Regards,

santhu_gowdaz
Active Contributor
0 Kudos

<m:Texttext="{myColumn}" wrapping="false" class="{=${color}=='yes'?'tableColor':''}">

css file :-

.tableColor{ background-color:#f9f9c2 !important; font-weight: bold; }

Refer : -

https://sapui5.hana.ondemand.com/#/api/sap.ui.core.Control/methods/addStyleClass

0 Kudos

Thanks Santhosh. Also I tried this solution exactly, with Text but it doesn't work ... I don't know. Any idea?

<Text text="{modelo>propiedad}"  wrapping="false" class="{= ${modelo>propiedad}=='si'?'colorClass':''}" > </Text>

The sergeyzh solution works well, but i have an Input and doesn't work.

Regards

0 Kudos

Hi Sergey, thanks so much.

I'm new in sapui5... i don't understand well ... the color is asign automatically when you change the value to "yes"?

The problem in your post " Therefore, when I scroll table down the rows 2, 4 ,8 are colored permanently. " is solved ??

Regards,

Initially, I was trying to find a way to use JS capabilities of the Table control inside my controller to add style class. In this case, it allowed managing only visible rows (unfortunately).

By using customData control in XML view, I could avoid this "visible rows" issue.

Consider an example,

we have JSON model containing an array of JSON objects (basically, our data): [{column1: "value1", column2: "value2"}, {...}, {...}]

I know that an object that has "Subtotal" as a value should be highlighted (all cells in that row should be highlighted): [{coumn1: "Subtotal", column2: "1234"}, {column1: "some data", column2: "345"}, {...},...]. Here I have Subtotal in row 1 (first object in the array). While I am looping through and looking for desired objects, I add another property to each of them: myJSONdata.color = "yes" /"no"

At the end, I have modified JSON data: [{column1: "Subtotal", column2: "1234", color: "yes"}, {column1: "some data", column2: "345", color: "no"},...{...}]

Thats all we need as a preparation.

Next, customData in our view does its job. It checks {color} of each cell and css file applies styling based on key-value pairs returned from customData control.

So, color is being assigned by css file where you add this: span[data-mydata="yes"] { background-color:#f9f9c2 !important; font-weight: bold; }

Original issue has not been solved. I used an alternative approach to make it work.

0 Kudos

Hi Sergey.

Do you find any solutions for getRows()? only return visible rows, i need all the rows ... for update the cell color, i have an input text in the cell don't find any solution!

Thanks

0 Kudos

In short, no. But I found another acceptable solution - changing cell color. Overall, it is not solid throughout the whole row, but it highlights cells within the row which was enough for me.

In controller,

1. I used json model. For each object in the JSON array, I added another property (say "color").

2. For desired objects (in my case with totals and subtotals) I set color to whatever ("yes")

3. For undesired objects - set color to different value.

In the view,

for each column, I added CustomData control that binds "color" property of JSON objects (from above)

<Column width="6em" 
        sortProperty="myColumn" 
        filterProperty="myColumn">
	<m:Label text="My Column" design="Bold"/>
	<template>
	<m:Text text="{myColumn}" wrapping="false">
		<m:customData>
               <core:CustomData key="mydata" value="{color}" writeToDom="true"></core:CustomData>
                </m:customData>
	</m:Text>
	</template>
</Column>

In css file, it checks key-value pairs from CustomData control. Key is "mydata". Value is whatever value the property "color" contains.

If color is set to "yes" means we want to highlight that cell --> it applies the styling, otherwise it ignores.

span[data-mydata="yes"] { background-color:#f9f9c2 !important; font-weight: bold; }

I know there should be a better solution, but hope it helps too! Thanks

0 Kudos

christian.libich5 I am on 1.44.11 version. Thanks!

0 Kudos

arun.krishna567 It gives me "failed to load" error. I believe <customData> element should be within a specific control, in my case it was within <Text>. If I put it after <columns> instead, the error comes out. Thanks!

0 Kudos

Hi Christian,

Unfortunately, I couldn't make it work. My factory function gets invoked, but sId and oContext parameters are both undefined. Thus, I couldn't move any further with this. Thanks for your help!

former_member185280
Active Contributor
0 Kudos

What version are you on?

0 Kudos

This approach does not fulfill my requirements stated above, but at least does color cells. Unfortunately, I could not figure out how to color rows. Hopefully, it my help someone. Please if somebody knows the better way, let us know. Thanks!

former_member185280
Active Contributor
0 Kudos

Sergey,

Where you able to make use of the solution I posted previously?

Regards,
Christian

0 Kudos
Assume, we get oData = [{}, {},   ,{}] with data. 
First, add a new property to each of the object in array, lets say: set color: "blue" for desired row cells, and "red" for everything else.
Second, set this data to our model: oModel.setData(oData);
Third, attach model to the table: this.getView().byId("table1").setModel(oModel);
In XML view we define our table as following (it is sap.ui.table with desired properties):
<Table id="table1"
	rows="{/}"
	title="Products"
	selectionMode="MultiToggle"
	fixedColumnCount="2"
	visibleRowCount="15">
<columns>
	<Column width="6em">
	<m:Label text="Column 1" />
	<template>
	   <m:Text text="{column1}" wrapping="false">
	   <m:customData>
              <core:CustomData key="mydata" value="{color}" writeToDom="true"></core:CustomData>
           </m:customData>
	   </m:Text>
	</template>
	</Column>
        

//continue in similar way 
       <Column>....................</Column>
</columns>
</Table>


In CSS file add the following:

span[data-mydata="blue"] {
background-color:#f9f9c2 !important;
}


In this case, key is "mydata", value is the value of each cell ( value="{color}"). If value is blue then we aply the color to this cell. 
arun_krishna567
Explorer
0 Kudos

Hi Sergey,

Try in the following way,

<Tableid="table1"rows="{/}"title="Products"
	selectionMode="MultiToggle"
	fixedColumnCount="2"
	visibleRowCount="15">
<columns>
<m:customData><core:CustomData key="mydata" value="{color}" writeToDom="true"></core:CustomData></m:customData>
<Columnwidth="6em"><m:Label text="Column 1" /><template><m:Texttext="{column1}" wrapping="false"></m:Text></template></Column>

And update your CSS accordingly.

Hope this will solve your issue...

maheshpalavalli
Active Contributor
0 Kudos

Hi Sergey Koch,

SAP.UI.TABLE only changes the data in the visible rows when you scroll unlike the SAP.M table which create new ui elements for new rows.

As the rows never change in SAP.UI table, you can use onAfterRendering event of the table and remove the style class and add the style class again(as per your logic). Now in this event, if you check the getRows(), you will find the latest rows.

Ideally speaking you can bind the style class to a formatter and change it based on the row data, but when i tried last time binding didnt work for the class property(style) for the controls.. I am not sure if it works in current releases, but you can check that as well.

BR,

Mahesh

0 Kudos

Thank you Mahesh! I don't know why, but onAfterRendering methos has never been invoked. I tried attach it to the table and override it: oTable.onAfterRendering = function(){ .....code....}

Or

oTable.addEventDelegate({ "onAfterRendering": function () {....code......} }, this);

In both cases, the code flow never went inside these functions when I was scrolling my table up and down.

Thanks!

developerone
Contributor
0 Kudos

To add a style class I need, first, get desired rows to apply that styling to. However, I cannot get all the desired rows because getRows() does return only visible rows. Thanks!