Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Customize ng-options selection look

I'm using a ng-options for a select dropdown menu. I would like to use different color for an option depending on a condition:

select(ng-model='myCompany', ng-options='company.code as company.name for company in companies' **if company.active -> text-color=green**)

Is it possible to do that?

Edit (my jade code):

 form(role='form', name='addForm', novalidate, rc-submit="add()")
    .form-group
        div.row
            div.col-xs-12.col-md-3
                select.form-control(ng-model='form.contract', ng-options='contract as contract.number for contract in contracts', options-class="{true:'active',false:'inactive'}[active]")
like image 679
ncohen Avatar asked Jul 08 '14 12:07

ncohen


3 Answers

If you only need to bind the select to string values (not object), you can easily achieve what you want by using ngRepeated <option> elements (instead of ngOptions):

<select ng-model="color">
  <option value="">--- Select a color ---</option>
  <option value="{{ c }}" style="background-color:{{ c }}" ng-repeat="c in colors">
    {{ c }}
  </option>
</select>

If you are in for a little custom directive, you can implement it like this:

app.directive('optionClassExpr', function ($compile, $parse) {
  const NG_OPTIONS_REGEXP = /^\s*([\s\S]+?)(?:\s+as\s+([\s\S]+?))?(?:\s+group\s+by\s+([\s\S]+?))?\s+for\s+(?:([\$\w][\$\w]*)|(?:\(\s*([\$\w][\$\w]*)\s*,\s*([\$\w][\$\w]*)\s*\)))\s+in\s+([\s\S]+?)(?:\s+track\s+by\s+([\s\S]+?))?$/;
  
  return {
    restrict: 'A',
    link: function optionClassExprPostLink(scope, elem, attrs) {
      const optionsExp = attrs.ngOptions;
      if (!optionsExp) return;
      
      const match = optionsExp.match(NG_OPTIONS_REGEXP);
      if (!match) return;
      
      const values = match[7];
      const classExpr = $parse(attrs.optionClassExpr);
      
      scope.$watchCollection(() => elem.children(), newValue => {
        angular.forEach(newValue, child => {
          const child = angular.element(child);
          const val   = child.val();
          if (val) {
            child.attr('ng-class', `${values}[${val}].${attrs.optionClassExpr}`);
            $compile(child)(scope);
          }
        });
      });
    }
  };
});

And use it like this:

<select
    ng-model="someObj"
    ng-options="obj as obj.color for obj in objects"
    option-class-expr="color">
</select>

See, also, this updated short demo.

like image 84
gkalpak Avatar answered Oct 19 '22 13:10

gkalpak


Define your CSS classes:

.green {
    background-color: green;   
}

.blue {
    background-color: blue;
}

and use a function as an angular expression:

$scope.getCompanyClass = function(company)
{
   return company.active ? "green" : "blue";
}

and in your html:

<select>
    <option data-ng-repeat="company in companies" data-ng-class='getCompanyClass(company)'>...</option>
</select>

and the working example as jsfiddle

like image 43
Raphael Müller Avatar answered Oct 19 '22 15:10

Raphael Müller


There is a neat solution for the special case that you want to show disabled options in a certain color. You can use disable when:

ng-options='c.code as c.name disable when !c.active for c in companies'

You can then use CSS to match on the disabled attribute and style the respective options the way you like.

like image 1
lex82 Avatar answered Oct 19 '22 15:10

lex82