warunkowe inline w angular.js

192

Zastanawiałem się, czy istnieje kątowy sposób warunkowego wyświetlania treści inny niż użycie ng-show itp. Na przykład w backbone.js mógłbym zrobić coś z zawartością wbudowaną w szablonie, takim jak:

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

ale pod kątem wydaje się, że ograniczam się do pokazywania i ukrywania rzeczy owiniętych w tagi HTML

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

Jaki jest zalecany sposób wyświetlania kątowego warunkowego wyświetlania i ukrywania treści wbudowanych w angularu za pomocą {{}} zamiast zawijania zawartości w tagach HTML?

użytkownik1469779
źródło
6
proszę, nie akceptuj mojej odpowiedzi i zaakceptuj 2Toad, gdy pojawi się szansa.
Ben Lesh,

Odpowiedzi:

139

EDYCJA: Odpowiedź 2Toad poniżej jest tym, czego szukasz! Głosuj za tym

Jeśli używasz Angulara <= 1.1.4, ta odpowiedź zrobi:

Jeszcze jedna odpowiedź na to. Podaję osobną odpowiedź, ponieważ jest to bardziej „dokładna” próba rozwiązania niż lista możliwych rozwiązań:

Oto filtr, który wykona „natychmiastowe, jeśli” (alias iif):

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

i mogą być używane w następujący sposób:

{{foo == "bar" | iif : "it's true" : "no, it's not"}}
Ben Lesh
źródło
Dziękuję, kochanie, po to właśnie chciałem. Zauważam jednak, że jeśli spróbuję umieścić znacznik HTML w jednej z wartości, psuje się: {{thing.second == "two" | iif: "<ul class = 'two-class'>": "<ul>"}} Zdaję sobie sprawę, że mogą istnieć lepsze sposoby na zrobienie tego pod kątem, ale czy istnieje sposób na ucieczkę "<" i ">" aby tagi mogły być wyprowadzane jako część ciągu?
user1469779,
1
ngBind nie pozwala na wyjście HTML, chciałbyś użyć ng-bind-html-unsafe
Ben Lesh
Przykład ng-binf-html-unsafe w dokumentacji kątowej używa go w znaczniku, na przykład <DOWOLNY ng-bind-html-unsafe = "{wyrażenie}">. może nie być możliwe robienie tego, co próbuję zrobić inline.
user1469779,
1
IIF to skrót od „Inline If”. Jest powszechny w różnych językach programowania ... po prostu nie tak powszechny jak?: Wbudowane ifs. ;)
Ben Lesh
18
@BenLesh główne rekwizyty do edycji odpowiedzi teraz, gdy są inne opcje, dobra robota.
Nick Coad
724

Dodano obsługę Angular 1.1.5 dla operatorów trójskładnikowych:

{{myVar === "two" ? "it's true" : "it's false"}}
2 Załaduj
źródło
14
Ta odpowiedź z największą liczbą głosów powinna znaleźć się u góry odpowiedzi ... jest zdecydowanie najbardziej poprawna
Code Whisperer
3
user1469779 rozważ zaakceptowanie tej odpowiedzi, ponieważ jest to zalecany sposób osiągnięcia tego, czego chcesz od dłuższego czasu
Filip Kis,
13
@ 2Toad, moja odpowiedź była stara. to jest prawidłowa odpowiedź teraz, nie wiem, czy użytkownik wróci, by ją „zaakceptować” teraz, ale jako taką opatrzyłem adnotację. Takie jest zmieniające się oblicze rozwoju oprogramowania.
Ben Lesh,
2
Dzięki. Jak mogę wyświetlać wartość myVartylko wtedy, gdy jest fałszywa? (tzn. jak zagnieżdżać zmienne w wyrażeniu?) Próbowałem z, {{myVar === "two" ? "it's true" : {{myVar}}}}ale to nie działa.
Josh
6
@Josh, myVarwłaściwość nie musi być zawijana w dodatkowe nawiasy klamrowe, jest już w wyrażeniu. Spróbuj{{myVar === "two" ? "it's true" : myVar}}
2Toad
60

Tysiące sposobów na skórowanie tego kota. Zdaję sobie sprawę, że pytasz konkretnie o {{}}, ale dla innych, którzy tu przychodzą, myślę, że warto pokazać inne opcje.

funkcja na $ zakres (IMO, to jest twój najlepszy zakład w większości scenariuszy):

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

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

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

ng-show i ng-hide oczywiście:

 <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>

Filtr niestandardowy, jak sugerował Bertrand. (jest to najlepszy wybór, jeśli musisz robić to samo w kółko)

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

{{foo | myFilter}}

Lub niestandardowa dyrektywa:

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>

Osobiście w większości przypadków korzystałbym z funkcji w moim zasięgu, która utrzymuje znaczniki w czystości, a jego wdrożenie jest szybkie i łatwe. Chyba że, to znaczy, będziesz robić to samo od nowa w kółko, w takim przypadku skorzystałbym z sugestii Bertranda i stworzyłbym filtr lub ewentualnie dyrektywę, w zależności od okoliczności.

Jak zawsze najważniejsze jest to, że Twoje rozwiązanie jest łatwe w utrzymaniu i, mam nadzieję, że można je przetestować. A to całkowicie zależy od konkretnej sytuacji.

Ben Lesh
źródło
18

Korzystam z następujących opcji, aby warunkowo ustawić klasę attr, gdy nie można użyć klasy ng (na przykład podczas stylowania SVG):

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

To samo podejście powinno działać w przypadku innych typów atrybutów.

(Myślę, że musisz używać najnowszego niestabilnego Angulara, aby używać ng-attr-, aktualnie jestem na wersji 1.1.4)

Opublikowałem artykuł o pracy z AngularJS + SVG, który mówi o tym i powiązanych zagadnieniach. http://www.codeproject.com/Articles/709340/Implementing-a-Flowchart-with-SVG-and-AngularJS

Ashley Davis
źródło
15

Aby sprawdzić zmienną zawartość i mieć domyślny tekst, możesz użyć:

<span>{{myVar || 'Text'}}</span>
ezequielc
źródło
1
Dziękuję Ci! Próbowałem tego, ale brakuje mi cytatów wokół łańcucha :-)
Simona Adriani
Z jakiegokolwiek powodu ta składnia nie działa przy użyciu jednorazowych powiązań. {{:: myVar || „Tekst”}} nie będzie działać. Musi być bez ::
aoakeson
3

Jeśli dobrze cię zrozumiałem, myślę, że masz na to dwa sposoby.

Najpierw możesz wypróbować ngSwitch, a drugim możliwym sposobem byłoby stworzenie własnego filtra . Prawdopodobnie ngSwitch jest właściwym podejściem, ale jeśli chcesz ukryć lub pokazać zawartość wbudowaną tylko za pomocą filtra {{}}, możesz to zrobić.

Oto skrzypce z prostym filtrem jako przykładem.

<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';
}
Bertrand
źródło
3

Biblioteka Angular UI ma wbudowaną dyrektywę ui-if dla warunku w szablonie / Widoki do angular ui 1.1.4

Przykład: Wsparcie w Angular UI upto ui 1.1.4

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

ng-jeśli jest dostępny we wszystkich wersjach kątowych po 1.1.4

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

jeśli masz jakieś dane w zmiennej tablicowej, pojawi się tylko div

JQuery Guru
źródło
ui-ifzostał usunięty przynajmniej z najnowszej wersji angular-ui, ale od wersji kątowej 1.1.5 masz ng-if(z tego komentarza )
Dave Everitt 28.10.13
2

Tak więc w Angular 1.5.1 (istniała zależność aplikacji od niektórych innych zależności stosu MEAN, dlatego obecnie nie używam 1.6.4)

Działa to dla mnie, jak mówi OP {{myVar === "two" ? "it's true" : "it's false"}}

{{vm.StateName === "AA" ? "ALL" : vm.StateName}}
Tom Stickel
źródło
2

jeśli chcesz wyświetlić „Brak”, gdy wartość wynosi „0”, możesz użyć jako:

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

lub true false w kątowym js

<span> {{ $scope.amount === "0" ?  "False" : "True" }} </span>
Rizo
źródło
1

Działa nawet w egzotycznych sytuacjach:

<br ng-show="myCondition == true" />
Steffomio
źródło
0

Wrzucę moje do miksu:

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

ocenia to raz instrukcję if i nie dodaje nasłuchiwania, ALE można dodać dodatkowy atrybut do elementu, który ma zestaw-if o nazwie wait-for = "somedata.prop" i będzie czekał na ustawienie tych danych lub właściwości przed jednorazowa ocena instrukcji if. ten dodatkowy atrybut może być bardzo przydatny, jeśli czekasz na dane z żądania 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');
              });
            }
          }
        };
      }
    };
  });
btm1
źródło