Search code examples
angularjsng-classservicenowng-style

Is it possible to combine ng-class with ng-style


Our team is working in ServiceNow and have a general question about using ng-class in combination with ng-style. We've created a widget that are task tiles and want to color the borders based on their status (i.e. green for finished, red for overdue, yellow for pending, grey for optional).

Originally, we accomplished this with only using ng-class:

<div class="card" ng-click="task.finished ||c.onWidget(task)"
     ng-class="{'finished-border': task.finished,
                'overdue-border': !task.finished && task.isOverDue,
                'pending-border': !task.finished && !task.isOverDue,
                'optional-border': !task.finished && task.isOptional}">
.finished-border {
  border: solid 2px $success;
  pointer-events: none;
  opacity: 0.55;
}
.overdue-border {
  border: solid 2px $overdue;
}
.pending-border {
  border: solid 2px $due-today;
}
.optional-border {
  border: solid 2px $color-light;
}

However, in an effort to make the colors a bit more flexible, ServiceNow allows the use of an option schema where users can choose what colors they want to give their finished, overdue, pending, and optional tasks. Since option schemas cannot be used in CSS, we were wondering if there's a way to combine the use of ng-style with ng-class. We've tried the following, but it did not work:

In our client script we tried something like this:

c.finished = {
  "border" : "solid 2px " + c.options.finished_color,
  "pointer-events" : "none",
  "opacity" : "0.55"
}

c.overdue = {
  "border" : "solid 2px " + c.options.overdue_color
}

c.pending = {
  "border" : "solid 2px " + c.options.pending_color
}

c.optional = {
  "border" : "solid 2px " + c.options.optional_color
}
<div class="card" ng-click="task.finished ||c.onWidget(task)"
     ng-class="{'c.finished': task.finished,
                'c.overdue': !task.finished && task.isOverDue,
                'c.pending': !task.finished && !task.isOverDue,
                'c.optional': !task.finished && task.isOptional}"> 

Is this even possible? Is there another way we can accomplish this?

Thanks!


Solution

  • You could use ng-style instead of ng-class.

    In this case:

    <div class="card" ng-click="task.finished ||c.onWidget(task)" 
         ng-class="{'c.finished': task.finished, 
                    'c.overdue': !task.finished && task.isOverDue, 
                    'c.pending': !task.finished && !task.isOverDue, 
                    'c.optional': !task.finished && task.isOptional}">
    

    The ng-class will add a class in your div like the string you defined, e.g:

    If task.finished is true, then your div will look like this:

    <div class="card c.finished" ng-click="task.finished ||c.onWidget(task)" 
         ng-class="{'c.finished': task.finished, 
                    'c.overdue': !task.finished && task.isOverDue, 
                    'c.pending': !task.finished && !task.isOverDue, 
                    'c.optional': !task.finished && task.isOptional}">
    

    Note that the class added was "c.finished" and not the style you defined.

    An idea would be to create a function in your controller to set the ng-style:

    function myDivStyle(task){
      if (task.finished) {
        return c.finished;
      } else if (!task.finished && task.isOverDue) {
        return c.overdue;
      } (...)
    }
    

    and then call this function in your div with ng-style:

    <div class="card" ng-click="task.finished ||c.onWidget(task)" 
         ng-style="myDivStyle(task)">
    

    This should work like what you want.