Inline-Bedingungen in angle.js

192

Ich habe mich gefragt, ob es in Angular eine Möglichkeit gibt, Inhalte bedingt anzuzeigen, außer ng-show usw. Zum Beispiel in backbone.js könnte ich etwas mit Inline-Inhalten in einer Vorlage tun, wie:

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

Aber im Winkel beschränke ich mich anscheinend darauf, Dinge in HTML-Tags zu zeigen und zu verstecken

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

Was ist die empfohlene Methode in Angular, um Inline-Inhalte in Angular nur mit {{}} bedingt anzuzeigen und auszublenden, anstatt sie in HTML-Tags zu verpacken?

user1469779
quelle
6
Bitte akzeptiere meine Antwort nicht und akzeptiere 2Toads, wenn du eine Chance hast.
Ben Lesh

Antworten:

139

EDIT: 2Toads Antwort ist genau das, wonach Sie suchen! Stimmen Sie das Ding ab

Wenn Sie Angular <= 1.1.4 verwenden, reicht diese Antwort aus:

Noch eine Antwort darauf. Ich poste eine separate Antwort, da es sich eher um einen "exakten" Lösungsversuch als um eine Liste möglicher Lösungen handelt:

Hier ist ein Filter, der ein "sofortiges Wenn" ausführt (auch bekannt als iif):

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

und kann wie folgt verwendet werden:

{{foo == "bar" | iif : "it's true" : "no, it's not"}}
Ben Lesh
quelle
Danke, meine Güte, das war es, was ich wollte. Ich bemerke jedoch, dass wenn ich versuche, ein HTML-Tag in einen der Werte einzufügen, es bricht: {{thing.second == "two" | iif: "<ul class = 'two-class'>": "<ul>"}} Mir ist klar, dass es bessere Möglichkeiten gibt, dies im Winkel zu tun, aber es gibt eine Möglichkeit, "<" und ">" zu entkommen. damit Tags als Teil der Zeichenfolge ausgegeben werden können?
user1469779
1
ngBind erlaubt keine HTML-Ausgabe, Sie möchten ng-bind-html-unsicher verwenden
Ben Lesh
Das Beispiel von ng-binf-html-unsafe in der eckigen Dokumentation verwendet es innerhalb eines Tags, z. B. <ANY ng-bind-html-unsafe = "{expression}">. Es ist möglicherweise nicht möglich, das zu tun, was ich versuche, inline zu tun.
user1469779
1
IIF ist die Abkürzung für "Inline If". Es ist in verschiedenen Programmiersprachen üblich ... nur nicht so häufig wie ?: Inline ifs. ;)
Ben Lesh
18
@ BenLesh wichtige Requisiten für die Bearbeitung Ihrer Antwort jetzt, da es andere Optionen gibt, gute Arbeit.
Nick Coad
724

Angular 1.1.5 hat Unterstützung für ternäre Operatoren hinzugefügt:

{{myVar === "two" ? "it's true" : "it's false"}}
2Laden
quelle
14
Diese Antwort mit den meisten Upvotes sollte oben in den Antworten erscheinen ... es ist bei weitem die richtigste
Code Whisperer
3
user1469779 erwägen, diese Antwort zu akzeptieren, da dies der empfohlene Weg ist, um das zu erreichen, was Sie für einige Zeit wollen
Filip Kis
13
@ 2Toad, meine Antwort war alt. Dies ist jetzt die richtige Antwort. Ich weiß nicht, ob der Benutzer sie jetzt wieder "akzeptieren" wird, aber ich habe meine Antwort als solche kommentiert. Dies ist das sich wandelnde Gesicht der Softwareentwicklung.
Ben Lesh
2
Vielen Dank. Wie kann ich den Wert myVarnur anzeigen lassen, wenn er falsch ist? (dh wie kann ich Variablen im Ausdruck verschachteln?) Ich habe es versucht, {{myVar === "two" ? "it's true" : {{myVar}}}}aber es funktioniert nicht.
Josh
6
@Josh, die myVarEigenschaft muss nicht in zusätzliche geschweifte Klammern eingeschlossen werden, sie befindet sich bereits in einem Ausdruck. Versuchen Sie{{myVar === "two" ? "it's true" : myVar}}
2Toad
60

Tausende Möglichkeiten, diese Katze zu häuten. Mir ist klar, dass Sie speziell zwischen {{}} fragen, aber für andere, die hierher kommen, lohnt es sich, einige der anderen Optionen aufzuzeigen.

Funktion auf Ihrem $ scope (IMO, dies ist in den meisten Szenarien die beste Wahl):

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

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

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

ng-show und ng-hide natürlich:

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

Ein benutzerdefinierter Filter, wie Bertrand vorgeschlagen hat. (Dies ist Ihre beste Wahl, wenn Sie immer wieder das Gleiche tun müssen.)

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

{{foo | myFilter}}

Oder eine benutzerdefinierte Anweisung:

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>

Persönlich würde ich in den meisten Fällen eine Funktion in meinem Bereich verwenden, die das Markup ziemlich sauber hält und schnell und einfach zu implementieren ist. Es sei denn, Sie werden immer und immer wieder genau das Gleiche tun. In diesem Fall würde ich Bertrands Vorschlag folgen und je nach den Umständen einen Filter oder möglicherweise eine Direktive erstellen.

Wie immer ist das Wichtigste, dass Ihre Lösung einfach zu warten und hoffentlich testbar ist. Und das hängt ganz von Ihrer spezifischen Situation ab.

Ben Lesh
quelle
18

Ich verwende Folgendes, um die Klasse attr bedingt festzulegen, wenn ng-class nicht verwendet werden kann (zum Beispiel beim Stylen von SVG):

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

Der gleiche Ansatz sollte für andere Attributtypen funktionieren.

(Ich denke, Sie müssen auf dem neuesten instabilen Angular sein, um ng-attr- verwenden zu können. Ich bin derzeit auf 1.1.4)

Ich habe einen Artikel über die Arbeit mit AngularJS + SVG veröffentlicht, der über dieses und verwandte Themen spricht. http://www.codeproject.com/Articles/709340/Implementing-a-Flowchart-with-SVG-and-AngularJS

Ashley Davis
quelle
15

Zum Überprüfen eines variablen Inhalts und eines Standardtexts können Sie Folgendes verwenden:

<span>{{myVar || 'Text'}}</span>
ezequielc
quelle
1
Danke! Ich habe es versucht, aber ich vermisse die Anführungszeichen um die Zeichenfolge :-)
Simona Adriani
Aus irgendeinem Grund funktioniert diese Syntax nicht mit einmaligen Bindungen. {{:: myVar || 'Text'}} funktioniert nicht. Muss ohne die ::
aoakeson
3

Wenn ich dich gut verstanden habe, denke ich, dass du zwei Möglichkeiten hast, es zu tun.

Erstens könnten Sie ngSwitch ausprobieren und der zweite Weg wäre, einen eigenen Filter zu erstellen . Wahrscheinlich ist ngSwitch der richtige Ansatz, aber wenn Sie Inline-Inhalte nur mit dem {{}} Filter ausblenden oder anzeigen möchten, ist dies der richtige Weg.

Hier ist eine Geige mit einem einfachen Filter als Beispiel.

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

Die Angular UI-Bibliothek verfügt über eine integrierte Direktive ui-if für Bedingungen in Vorlagen / Ansichten bis zu Angular UI 1.1.4

Beispiel: Unterstützung in Angular UI bis UI 1.1.4

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

ng-falls in allen Winkelversionen nach 1.1.4 verfügbar

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

Wenn Sie Daten in der Array-Variablen haben, wird nur das div angezeigt

JQuery Guru
quelle
ui-ifwurde zumindest aus der neuesten Version angle-ui entfernt, aber seit Angular 1.1.5 haben Sie ng-if(aus diesem Kommentar )
Dave Everitt
2

Also mit Angular 1.5.1 (hatte vorhandene App-Abhängigkeit von einigen anderen MEAN-Stack-Abhängigkeiten, warum ich derzeit nicht 1.6.4 verwende)

Das funktioniert bei mir wie das OP-Sprichwort {{myVar === "two" ? "it's true" : "it's false"}}

{{vm.StateName === "AA" ? "ALL" : vm.StateName}}
Tom Stickel
quelle
2

Wenn Sie "Keine" anzeigen möchten, wenn der Wert "0" ist, können Sie Folgendes verwenden:

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

oder wahr falsch in eckigen js

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

Funktioniert auch in exotischen Situationen:

<br ng-show="myCondition == true" />
Steffomio
quelle
0

Ich werde meine in die Mischung werfen:

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

Dies wertet die if-Anweisung einmal aus und fügt keinen Watch-Listener hinzu, ABER Sie können dem Element mit dem set-if-Wert wait-for = "somedata.prop" ein zusätzliches Attribut hinzufügen, das darauf wartet, dass diese Daten oder Eigenschaften zuvor festgelegt werden einmalige Auswertung der if-Anweisung. Dieses zusätzliche Attribut kann sehr praktisch sein, wenn Sie auf Daten aus einer XHR-Anforderung warten.

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
quelle