set row background color based on field value not working

  • 1
  • Problem
  • Updated 3 years ago
  • Solved


var field = arguments[0], 
    value = skuid.utils.decodeHTML(arguments[1]); 

skuid.ui.fieldRenderers[field.metadata.displaytype][field.mode](field,value); 

if (value == 'Prospect') {
    field.item.element.closest('tr').css( "background-color","#0066ff");
} else if (value == 'Contacted')  {
    field.item.element.closest('tr').css( "background-color","#6600ff");
} else if (value == 'Interested')  {
    field.item.element.closest('tr').css( "background-color","#ff0000");
} else if (value == 'Confirmed')  {
    field.item.element.closest('tr').css( "background-color","#009900");
} else if (value == 'Cancelled')  {
    field.item.element.closest('tr').css( "background-color","#b2b2b2");
} else if (value == 'Replaced')  {
    field.item.element.closest('tr').css( "background-color","#ff99ff");
} else if (value == 'Badged')  {
    field.item.element.closest('tr').css( "background-color","#ffc000");
} else if (value == 'Dead')  {
    field.item.element.closest('tr').css( "background-color","#000000");
}
Photo of mB Pat Vachon

mB Pat Vachon, Champion

  • 42,714 Points 20k badge 2x thumb

Posted 3 years ago

  • 1
Photo of mB Pat Vachon

mB Pat Vachon, Champion

  • 42,714 Points 20k badge 2x thumb
Have updated my snippet and it kinds works. Just not on page load.

Photo of Barry Schnell

Barry Schnell, Champion

  • 18,076 Points 10k badge 2x thumb
Hey Pat -

The video you posted appears cropped in some way so its difficult to see what's going on.  If I understood the audio correctly, you want a specific table cell to have a background color based on its value.

In the code you have posted, your setting the tr (row) element background.  When skuid renders the table, it applies background colors to td & div so those will override any background on the tr.  Given this, I'm assuming you possible adjusted your code to use the td or div inside the row.  As for not getting it to display on page load, my only thought here is that possibly your adjusted code is using a selector to grab the parent of the element or something.  When skuid renders elements, it doesn't attach the the new element to its parent until after the element is rendered so using a selector like "closest" or "parent" or anything that would try to go "up" the DOM won't find anything on page load.  It will, in some situations, find things on subsequent rendering cycles (because it was already attached on page load).  Depending on how your code sits now, this could explain why it doesn't work on page load but does later on.

All that said, I think there is a slightly easier and more maintainable approach for what you are doing.  Rather than have a big long "if...then" block in the renderer, you can use css classes to achieve the desired result and give you more flexibility.  You can use the "value" to add a css class and then decorate that class in css the way you want.

See the sample page below.  In it, I provide two different ways of decorating the cell. 

1) Add the class to the tr itself and use the nth-child selector for the field you want decorated. Fortunately, the CSS3 spec is adding parent selectors but most browsers do not support them yet. If we had parent selectors, you could add the class to the field.element itself and then use a parent selector to decorate the entire TD.  You can use the nth-child selector approach if you want to decorate the entire TD

2) Add the class to the field element itself - This approach decorates the DIV inside the TD.

Using either of the above approaches, when you come across new "values" to support, you just update your CSS adding new classes as appropriate.

Hope this helps!

<skuidpage unsavedchangeswarning="yes" personalizationmode="server" showsidebar="true" showheader="true" tabtooverride="Account">   <models>
      <model id="Account" limit="100" query="true" createrowifnonefound="false" sobject="Account" adapter="" type="">
         <fields>
            <field id="Name"/>
            <field id="CreatedDate"/>
            <field id="Type"/>
         </fields>
         <conditions/>
         <actions/>
      </model>
   </models>
   <components>
      <pagetitle model="Account" uniqueid="sk-3dqT0f-66">
         <maintitle>
            <template>{{Model.labelPlural}}</template>
         </maintitle>
         <subtitle>
            <template>Home</template>
         </subtitle>
         <actions>
            <action type="savecancel"/>
         </actions>
      </pagetitle>
      <skootable showconditions="true" showsavecancel="false" searchmethod="server" searchbox="true" showexportbuttons="false" pagesize="10" createrecords="true" model="Account" mode="read" uniqueid="sk-3dqT0f-67">
         <fields>
            <field id="Name" allowordering="true"/>
            <field id="CreatedDate" allowordering="true"/>
            <field id="Name"/>
            <field id="Type" valuehalign="" type="CUSTOM" snippet="accountTypeRenderer"/>
         </fields>
         <rowactions>
            <action type="edit"/>
            <action type="delete"/>
         </rowactions>
         <massactions usefirstitemasdefault="true"/>
         <views>
            <view type="standard"/>
         </views>
      </skootable>
   </components>
   <resources>
      <labels/>
      <css>
         <cssitem location="inline" name="newcss" cachelocation="false">.customer-channel-item td:nth-child(5) {
    border: 1px solid green;
}
.customer-direct-item td:nth-child(5) {
    border: 1px solid orange;
}
.customer-channel-field {
    background-color: red;
}
.customer-direct-field {
    background-color: blue;
}</cssitem>
      </css>
      <javascript>
         <jsitem location="inlinesnippet" name="accountTypeRenderer" cachelocation="false">var $ = skuid.$
    , field = arguments[0]
    , value = skuid.utils.decodeHTML(arguments[1])
    , cleanedValue = value &amp;&amp; value.replace(/\s+/g, '').toLowerCase();
skuid.ui.fieldRenderers[field.metadata.displaytype][field.mode](field,value); 
if (cleanedValue) {
    $(field.element).addClass(cleanedValue + '-field');
    $(field.item.element).addClass(cleanedValue + '-item');
}</jsitem>
      </javascript>
   </resources>
   <styles>
      <styleitem type="background" bgtype="none"/>
   </styles>
</skuidpage>
(Edited)
Photo of mB Pat Vachon

mB Pat Vachon, Champion

  • 42,714 Points 20k badge 2x thumb
This is what I was afraid of. I think I can use the Originals object in the model to remove the old class prior to adding the new class. That way I won't have any hard coded classes to clear out. Only place I'll have to manage manually is the classes & colors in the CSS. Otherwise pretty clean.

I like how you've dynamically set the classes on item and field based on the field value. Slick.
Photo of Barry Schnell

Barry Schnell, Champion

  • 18,076 Points 10k badge 2x thumb
If you want to allow "editing" of the field and changing the colors, you could use originals or you could use your own data to track the old/new.  Below is a sample of how to do that.

If you really want to get slick you could subscribe to model updated and change the color of the background as the user edits the field value without having to wait for a new rendering cycle.  To do this, you just need to be sure to subscribe to model updated only one time - don't do it every time through the rendering cycle or you will end up with multiple event listeners.

Here's the sample modified using data instead of originals:
var $ = skuid.$    , field = arguments[0]
    , value = skuid.utils.decodeHTML(arguments[1])
    , dataKey = 'myns-curvalue'
    , curValue = $(field.element).data(dataKey)
    , newValue = (value && value.replace(/[\s|//]+/g, '').toLowerCase()) || 'no-value';    
// if there is a current value, remove the classes
if (curValue) {
    $(field.element).removeClass(curValue + '-field');
    $(field.item.element).removeClass(curValue + '-item');
}
// render the field
skuid.ui.fieldRenderers[field.metadata.displaytype][field.mode](field,value); 
// if we have a new value (which we always should)
// add the class
if (newValue) {
    $(field.element).addClass(newValue + '-field');
    $(field.item.element).addClass(newValue + '-item');
}
// update the data
$(field.element).data(dataKey, newValue);
Photo of mB Pat Vachon

mB Pat Vachon, Champion

  • 42,714 Points 20k badge 2x thumb
Updated snippet to this.

var $ = skuid.$
    , field = arguments[0]
    , id = field.Id
    , model = field.model
    , value = skuid.utils.decodeHTML(arguments[1])
    , cleanedValue = value && value.replace(/\s+/g, '').toLowerCase();
    

if (cleanedValue) {

    $(field.element).removeClass (function (index, css) {
        return (css.match (/($|[^ ]+)-user-field/g) || []).join(' ');
    });
    $(field.item.element).removeClass (function (index, css) {
        return (css.match (/($|[^ ]+)-user-item/g) || []).join(' ');
    });
    
    $(field.element).addClass(cleanedValue + '-user-field');
    $(field.item.element).addClass(cleanedValue + '-user-item');
}

skuid.ui.fieldRenderers[field.metadata.displaytype][field.mode](field,value);
Photo of Barry Schnell

Barry Schnell, Champion

  • 18,076 Points 10k badge 2x thumb
Keep in mind you only need to use either the "-item" approach or the "-field" approach.  I just put both options in to the sample so you could have the option of decorating the TD or the DIV as I wasn't sure which one you wanted to decorate. 

The regex to clear the values should work but its going to likely be less performant than the "data" approach or using originals since it will loop through every class on the element.  In this case, there should only be 2  (nx-field or nx-item plus your class) but it's still one more than necessary to evaluate.