codelord.net

Code, Angular, iOS and more by Aviv Ben-Yosef

Stop ng-repeating options: use ng-options

| Comments

A pet peeve of mine is seeing Angular code with <select> tags that uses ng-repeat to generate the options, like so:

1
2
3
4
5
<select ng-model="$ctrl.mode">
  <option ng-repeat="option in $ctrl.options"
    ng-value="option" ng-bind="option.name">
  </option>
</select>

One of the great little details about Angular is the awesome ng-options directive, which I find more concise and is very powerful.

First, here is the basic translation of the above:

1
2
3
<select ng-model="$ctrl.mode"
  ng-options="o.name for o in $ctrl.options">
</select>

The trick here is that ng-options is completely in charge of creating the actual <option> elements for us.

Now, let’s see where it shines.

Nullability of a select

When using ng-options, once you initialize the ng-model value to one of the options there’s no way for the user to reset it to an empty value by default.

To allow setting it to null, we simply add a special empty <option> tag. Here’s how the above example would look with nullability:

1
2
3
4
<select ng-model="$ctrl.mode"
  ng-options="o.name for o in $ctrl.options">
  <option value=""></option>
</select>

Using an object as a value

Another thing is that a lot of developers miss the fact that Angular lets us use selects with values that aren’t simple strings, but actual objects.

In the first example I showed how you do it manually, using ng-value, instead of the value property. This tells Angular to bind to our model the actual object that the expression evaluates to.

ng-options of course does that automatically for us, but we can customize the bound value even more if needed, for example:

1
2
3
4
<select ng-model="$ctrl.mode"
  ng-options="o.value as o.name for o in $ctrl.options">
  <option value=""></option>
</select>

Disabling elements

Another reason that I usually prefer using native HTML elements and not wrappers (e.g. Select2) is because they usually pack so much under the hood.

For example, you can easily have a few options be disabled dynamically:

1
2
3
4
5
<select ng-model="$ctrl.mode"
  ng-options="o.name disable when $ctrl.disabled(o)
              for o in $ctrl.options">
  <option value=""></option>
</select>

The disable when clause lets you specify an expression that decides which options will be displayed but won’t be enabled for actual selection.

So, please, don’t roll your own <option> elements unless you have a good reason!

“Maintaining AngularJS feels like Cobol 🤷…”

You want to do AngularJS the right way.
Yet every blog post you see makes it look like your codebase is obsolete. Components? Lifecycle hooks? Controllers are dead?

It would be great to work on a modern codebase again, but who has weeks for a rewrite?
Well, you can get your app back in shape, without pushing back all your deadlines! Imagine, upgrading smoothly along your regular tasks, no longer deep in legacy.

Subscribe and get my free email course with steps for upgrading your AngularJS app to the latest 1.6 safely and without a rewrite.

Get the modernization email course!

Comments