Domanda

I am rather new to AngularJs, but I have a specific need for a more complex, conditional template using multiple interpolation symbols. I am using the same example as in https://docs.angularjs.org/api/ng/service/$interpolate .

I need something like:

[[ {{greeting}}, {{name}} || Hello, {{name}} || Hello, stranger ]]

This should be interpreted as a multiple conditional template, showing the first fragment if both $scope.greeting and $scope.name are defined, the second one if only $scope.name is defined, and the third one otherwise.

The idea is that within symbols [[ ]] the fragments between a || symbol are interpolated using the standard interpolation symbols with AllOrNothing, proceeding from left to right until the first one succeeds, and making sure that the last one always succeeds.

I know that this can be done with something like

<span ng-if='greeting && name">{{greeting}}{{name}}</span>
<span ng-if='name && !greeting">Hello, {{name}}</span>
<span ng-if='!name">Hello, stranger</span>

but this solution is extremely cumbersome, requires to determine which complex set of boolean expressions makes sure that only one span is shown, and adds spurious spans to the DOM just because you need a place for the ng-if directives.

Thank you for all you can suggest.

Nessuna soluzione corretta

Altri suggerimenti

You can write your own filter to handle this situation specifically. If you want something a little more reusable, in regards to conditional output, you could make an a kind of ternary filter. Here's one called iif (named as such to prevent eval errors we'd get if we called it just if):

.filter('iif', function() {
  // usage: {{ conditionToTest | iif:truevalue:falseValue }}
  // example: {{ iAmTrue | iif:'I am true':'I am false' }}
  return function(input, trueValue, falseValue) {
      return input ? trueValue : falseValue;
  };
})

Use it like this in your example:

{{greeting | iif:greeting:'Hello'}}, {{name | iif:name:'stranger'}}

You can certainly specialize it further, if that's too verbose:

.filter('valueOrDefault', function() {
    return function(input, defaultValue) {
        return input || defaultValue;
    };
})

Then your template looks like:

{{ greeting | valueOrDefault:'Hello' }}, {{name | valueOrDefault: 'stranger'}}

And so on.

The interpolator should be able to handle it.

<p>{{ greeting || 'Hello' }}, {{ name || 'Stranger' }}.</p>
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top