condizionali incorporati in angular.js


192

Mi chiedevo se esiste un modo in angolare per visualizzare in modo condizionale contenuto diverso dall'uso di ng-show ecc. Ad esempio in backbone.js potrei fare qualcosa con il contenuto incorporato in un modello come:

<% if (myVar === "two") { %> show this<% } %>

ma in angolare, mi sembra di limitarmi a mostrare e nascondere cose racchiuse in tag html

<p ng-hide="true">I'm hidden</p>
<p ng-show="true">I'm shown</p>

Qual è il modo consigliato in angolare per mostrare e nascondere in modo condizionale il contenuto in linea in angolare usando semplicemente {{}} anziché racchiudere il contenuto in tag html?


6
per favore, accetta la mia risposta e accetta 2Toad's quando hai una possibilità.
Ben Lesh,

Risposte:


139

EDIT: 2 La risposta di Toad di seguito è ciò che stai cercando! Valorizza quella cosa

Se stai usando Angular <= 1.1.4, questa risposta farà:

Un'altra risposta per questo. Sto postando una risposta separata, perché è più un tentativo "esatto" di una soluzione che un elenco di possibili soluzioni:

Ecco un filtro che farà un "if immediato" (aka iif):

app.filter('iif', function () {
   return function(input, trueValue, falseValue) {
        return input ? trueValue : falseValue;
   };
});

e può essere usato in questo modo:

{{foo == "bar" | iif : "it's true" : "no, it's not"}}

Grazie carne, questo è quello che stavo cercando. Tuttavia noto che se provo a inserire un tag html in uno dei valori, si rompe: {{thing.second == "two" | iif: "<ul class = 'two-class'>": "<ul>"}} Mi rendo conto che potrebbero esserci modi migliori per farlo in angolare, ma c'è un modo per sfuggire a "<" e ">" in modo che i tag possano essere emessi come parte della stringa?
user1469779

1
ngBind non consente l'output HTML, ti consigliamo di utilizzare ng-bind-html-unsafe
Ben Lesh

L'esempio di ng-binf-html-unsafe nella documentazione angolare lo utilizza all'interno di un tag, ad esempio <QUALSIASI ng-bind-html-unsafe = "{espressione}">. potrebbe non essere possibile fare ciò che sto cercando di fare in linea.
user1469779

1
IIF è l'abbreviazione di "Inline If". È comune in diversi linguaggi di programmazione ... non è così comune come?: Inline ifs. ;)
Ben Lesh,

18
@BenLesh principali oggetti di scena per modificare la tua risposta ora che ci sono altre opzioni, buon lavoro.
Nick Coad,

725

Angular 1.1.5 ha aggiunto il supporto per gli operatori ternari:

{{myVar === "two" ? "it's true" : "it's false"}}

14
Questa risposta con il maggior numero di voti dovrebbe apparire nella parte superiore delle risposte ... è di gran lunga la più corretta
Code Whisperer

3
user1469779 considera di accettare questa risposta in quanto questo è il modo raccomandato per raggiungere quello che vuoi per un bel po 'di tempo
Filip Kis

13
@ 2Toad, la mia risposta era vecchia. questa è la risposta corretta ora, non so se l'utente tornerà ad "accettarla" ora, ma ho annotato la mia risposta in quanto tale. Tale è il volto mutevole dello sviluppo del software.
Ben Lesh,

2
Grazie. Come posso visualizzare il valore di myVarsolo se è falso? (cioè come posso annidare le variabili nell'espressione?) Ho provato con {{myVar === "two" ? "it's true" : {{myVar}}}}ma non funziona.
Josh,

6
@Josh la myVarproprietà non ha bisogno di essere racchiusa tra parentesi graffe aggiuntive, è già dentro un'espressione. Prova{{myVar === "two" ? "it's true" : myVar}}
ricarica il

60

Migliaia di modi per scuoiare questo gatto. Mi rendo conto che stai chiedendo in particolare tra {{}}, ma per gli altri che vengono qui, penso che valga la pena mostrare alcune delle altre opzioni.

funzione sul tuo $ scope (IMO, questa è la tua scommessa migliore nella maggior parte degli scenari):

  app.controller('MyCtrl', function($scope) {
      $scope.foo = 1;

      $scope.showSomething = function(input) {
           return input == 1 ? 'Foo' : 'Bar';
      };
   });

 <span>{{showSomething(foo)}}</span>

ng-show e ng-hide ovviamente:

 <span ng-show="foo == 1">Foo</span><span ng-hide="foo == 1">Bar</span>

ngSwitch

 <div ng-switch on="foo">
   <span ng-switch-when="1">Foo</span>
   <span ng-switch-when="2">Bar</span>
   <span ng-switch-default>What?</span>
 </div>

Un filtro personalizzato come suggerito da Bertrand. (questa è la scelta migliore se devi fare sempre la stessa cosa)

app.filter('myFilter', function() {
   return function(input) {
     return input == 1 ? 'Foo' : 'Bar';
   }
}

{{foo | myFilter}}

O una direttiva personalizzata:

app.directive('myDirective', function() {
   return {
     restrict: 'E',
     replace: true,
     link: function(scope, elem, attrs) {
       scope.$watch(attrs.value, function(v) {
          elem.text(v == 1 ? 'Foo': 'Bar');
       });
     }
   };
});


<my-directive value="foo"></my-directive>

Personalmente, nella maggior parte dei casi andrei con una funzione sul mio ambito, mantiene il markup abbastanza pulito ed è veloce e facile da implementare. A meno che, cioè, continuerai a ripetere sempre la stessa identica cosa, nel qual caso seguirò il suggerimento di Bertrand e creerò un filtro o eventualmente una direttiva, a seconda delle circostanze.

Come sempre, la cosa più importante è che la tua soluzione è facile da mantenere ed è sperabilmente verificabile. E questo dipenderà completamente dalla tua situazione specifica.


18

Sto usando quanto segue per impostare condizionatamente la classe attr quando ng-class non può essere usata (ad esempio quando si disegna lo SVG):

ng-attr-class="{{someBoolean && 'class-when-true' || 'class-when-false' }}"

Lo stesso approccio dovrebbe funzionare per altri tipi di attributi.

(Penso che devi essere sull'ultimo Angolare instabile per usare ng-attr-, al momento sono su 1.1.4)

Ho pubblicato un articolo su come lavorare con AngularJS + SVG che parla di questo e di problemi correlati. http://www.codeproject.com/Articles/709340/Implementing-a-Flowchart-with-SVG-and-AngularJS


15

Per controllare un contenuto variabile e avere un testo predefinito, è possibile utilizzare:

<span>{{myVar || 'Text'}}</span>

1
grazie! Ci stavo provando ma mi mancano le virgolette attorno alla stringa :-)
Simona Adriani

Per qualsiasi motivo, questa sintassi non funziona utilizzando i collegamenti una tantum. {{:: myVar || 'Testo'}} non funzionerà. Deve essere senza:
aoakeson il

3

Se ti ho capito bene, penso che tu abbia due modi per farlo.

Per prima cosa potresti provare ngSwitch e il secondo modo possibile sarebbe creare il tuo filtro . Probabilmente ngSwitch è l'approccio giusto, ma se vuoi nascondere o mostrare contenuti inline, basta usare il filtro {{}}.

Ecco un violino con un semplice filtro come esempio.

<div ng-app="exapleOfFilter">
  <div ng-controller="Ctrl">
    <input ng-model="greeting" type="greeting">
      <br><br>
      <h1>{{greeting|isHello}}</h1>
  </div>
</div>

angular.module('exapleOfFilter', []).
  filter('isHello', function() {
    return function(input) {
      // conditional you want to apply
      if (input === 'hello') {
        return input;
      }
      return '';
    }
  });

function Ctrl($scope) {
  $scope.greeting = 'hello';
}

3

La libreria UI angolare ha una direttiva incorporata ui-if per la condizione in template / Views fino a ui angolare 1.1.4

Esempio: supporto nell'interfaccia utente angolare fino all'interfaccia utente 1.1.4

<div ui-if="array.length>0"></div>

ng-se disponibile in tutte le versioni angolari dopo 1.1.4

<div ng-if="array.length>0"></div>

se hai dati nella variabile array, apparirà solo il div


ui-ifè stato rimosso almeno dall'ultima versione angular-ui ma dalla versione 1.1.5 angolare che hai ng-if(da questo commento )
Dave Everitt,

2

Quindi con Angular 1.5.1 (la dipendenza dall'app esistente su alcune altre dipendenze dello stack MEAN è il motivo per cui non sto attualmente usando 1.6.4)

Questo funziona per me come dice il PO {{myVar === "two" ? "it's true" : "it's false"}}

{{vm.StateName === "AA" ? "ALL" : vm.StateName}}

2

se si desidera visualizzare "Nessuno" quando il valore è "0", è possibile utilizzare come:

<span> {{ $scope.amount === "0" ?  $scope.amount : "None" }} </span>

o vero falso in js angolare

<span> {{ $scope.amount === "0" ?  "False" : "True" }} </span>

1

Funziona anche in situazioni esotiche:

<br ng-show="myCondition == true" />

0

Lancio il mio nel mix:

https://gist.github.com/btm1/6802312

questo valuta una volta l'istruzione if e non aggiunge alcun listener di watch MA MA puoi aggiungere un attributo aggiuntivo all'elemento che ha il set-if chiamato wait-for = "somedata.prop" e aspetterà che i dati o la proprietà siano impostati prima valutazione dell'istruzione if una volta. quell'attributo aggiuntivo può essere molto utile se stai aspettando dati da una richiesta XHR.

angular.module('setIf',[]).directive('setIf',function () {
    return {
      transclude: 'element',
      priority: 1000,
      terminal: true,
      restrict: 'A',
      compile: function (element, attr, linker) {
        return function (scope, iterStartElement, attr) {
          if(attr.waitFor) {
            var wait = scope.$watch(attr.waitFor,function(nv,ov){
              if(nv) {
                build();
                wait();
              }
            });
          } else {
            build();
          }

          function build() {
            iterStartElement[0].doNotMove = true;
            var expression = attr.setIf;
            var value = scope.$eval(expression);
            if (value) {
              linker(scope, function (clone) {
                iterStartElement.after(clone);
                clone.removeAttr('set-if');
                clone.removeAttr('wait-for');
              });
            }
          }
        };
      }
    };
  });
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.