встроенные условия в angular.js

193

Мне было интересно, есть ли в angular способ условного отображения контента, кроме использования ng-show и т. Д. Например, в backbone.js я мог бы сделать что-то со встроенным контентом в шаблоне, например:

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

но в угловом я, кажется, ограничен показом и сокрытием вещей, завернутых в HTML-теги

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

Как рекомендуется использовать angular для условного отображения и скрытия встроенного содержимого в angular, просто используя {{}}, а не оборачивая содержимое в HTML-теги?

user1469779
источник
6
пожалуйста, не принимайте мой ответ, примите 2Toad, когда у вас есть шанс.
Бен Леш

Ответы:

139

РЕДАКТИРОВАТЬ: 2Toad ответ ниже , что вы ищете! Поддержи эту вещь

Если вы используете Angular <= 1.1.4, тогда ответ будет таким:

Еще один ответ на это. Я публикую отдельный ответ, потому что это скорее «точная» попытка решения, чем список возможных решений:

Вот фильтр, который будет выполнять «немедленное if» (он же iif):

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

и может быть использовано так:

{{foo == "bar" | iif : "it's true" : "no, it's not"}}
Бен Леш
источник
Спасибо тебе, боже, это то, к чему я стремился. Однако я заметил, что если я попытаюсь поместить html-тег в одно из значений, оно будет разбито: {{thing.second == "two" | iif: "<ul class = 'two-class'>": "<ul>"}} Я понимаю, что могут быть лучшие способы сделать это в угловых, но есть ли способ избежать "<" и ">" чтобы теги можно было выводить как часть строки?
user1469779
1
ngBind не разрешает вывод HTML, вы можете использовать ng-bind-html-unsafe
Бен Леш,
Пример ng-binf-html-unsafe в угловой документации использует его в теге, например <ANY ng-bind-html-unsafe = "{expression}">. может быть невозможно сделать то, что я пытаюсь сделать в строке.
user1469779
1
IIF - это сокращение от «Inline If». Это часто встречается в разных языках программирования ... просто не так часто, как?: Inline ifs. ;)
Бен Леш
18
@BenLesh основные реквизиты для редактирования вашего ответа теперь, когда есть другие варианты, хорошая работа.
Ник Коад
726

В Angular 1.1.5 добавлена ​​поддержка троичных операторов:

{{myVar === "two" ? "it's true" : "it's false"}}
2Toad
источник
14
Этот ответ с наибольшим количеством голосов должен появиться в верхней части ответов ... он, безусловно, самый правильный
Code Whisperer
3
user1469779 рассмотрите возможность принять этот ответ, так как это рекомендуемый способ достижения того, чего вы хотите, в течение достаточно долгого времени
Filip Kis
13
@ 2До, мой ответ был старым. сейчас это правильный ответ, я не знаю, вернется ли пользователь, чтобы «принять» его сейчас, но я прокомментировал свой ответ как таковой. Таково меняющееся лицо разработки программного обеспечения.
Бен Леш
2
Спасибо. Как я могу отображать значение, myVarтолько если оно ложно? (т.е. как я могу вкладывать переменные в выражение?) Я пытался, {{myVar === "two" ? "it's true" : {{myVar}}}}но это не работает.
Джош
6
@ Джош, myVarсвойство не нужно заключать в дополнительные фигурные скобки, оно уже внутри выражения. Попробуйте{{myVar === "two" ? "it's true" : myVar}}
2Toad
60

Тысячи способов снять шкуру с этой кошки. Я понимаю, что вы спрашиваете между {{}} конкретно, но для других, которые приходят сюда, я думаю, что стоит показать некоторые другие варианты.

Функция в вашей области $ (IMO, это ваша лучшая ставка в большинстве сценариев):

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

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

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

нг-шоу и нг-скрыть, конечно:

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

Пользовательский фильтр, как предложил Бертран. (это ваш лучший выбор, если вам придется делать одно и то же снова и снова)

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

{{foo | myFilter}}

Или пользовательская директива:

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>

Лично в большинстве случаев я бы использовал функцию в своей области видимости, она содержала разметку довольно чисто, и ее легко и быстро реализовать. Если, конечно, вы не будете делать одно и то же точно снова и снова, и в этом случае я бы следовал предложению Бертранда и создавал фильтр или, возможно, директиву, в зависимости от обстоятельств.

Как всегда, самое важное - это то, что ваше решение легко обслуживается и, как мы надеемся, тестируемо. И это будет полностью зависеть от вашей конкретной ситуации.

Бен Леш
источник
18

Я использую следующее, чтобы условно установить класс attr, когда ng-класс не может быть использован (например, при стилизации SVG):

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

Тот же подход должен работать для других типов атрибутов.

(Я думаю, что вы должны быть на последнем нестабильном Angular, чтобы использовать ng-attr-, я сейчас на 1.1.4)

Я опубликовал статью о работе с AngularJS + SVG, в которой говорится об этом и связанных с этим проблемах. http://www.codeproject.com/Articles/709340/Implementing-a-Flowchart-with-SVG-and-AngularJS

Эшли Дэвис
источник
15

Для проверки содержимого переменной и текста по умолчанию вы можете использовать:

<span>{{myVar || 'Text'}}</span>
ezequielc
источник
1
Спасибо! Я пытался это, но я пропускаю цитаты вокруг строки :-)
Симона Адриани
По какой-то причине этот синтаксис не работает с использованием одноразовых привязок .. {{:: myVar || «Текст»} не будет работать. Должно быть без ::
aoakeson
3

Если я вас хорошо понял, думаю, у вас есть два способа сделать это.

Сначала вы можете попробовать ngSwitch, а второй возможный способ - создать собственный фильтр . Возможно, ngSwitch - правильный подход, но если вы хотите скрыть или показать встроенный контент, используйте фильтр {{}}.

Вот в качестве примера скрипка с простым фильтром.

<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
источник
3

Библиотека Angular UI имеет встроенную директиву ui-if для условия в шаблоне / Views до angular ui 1.1.4

Пример: поддержка в Angular UI до пользовательского интерфейса 1.1.4

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

нг-если доступно во всех угловых версиях после 1.1.4

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

если у вас есть какие-либо данные в переменной массива, то появится только div

JQuery Гуру
источник
ui-ifбыл удален по крайней мере из последней версии angular-ui, но начиная с angular 1.1.5 у вас есть ng-if(из этого комментария )
Дейв Эверитт
2

Таким образом, с Angular 1.5.1 (существующая зависимость приложения от некоторых других зависимостей стека MEAN, поэтому я в настоящее время не использую 1.6.4)

Это работает для меня как высказывание ОП {{myVar === "two" ? "it's true" : "it's false"}}

{{vm.StateName === "AA" ? "ALL" : vm.StateName}}
Том Стиккель
источник
2

если вы хотите отобразить «None», когда значение равно «0», вы можете использовать как:

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

или правда ложь в угловых JS

<span> {{ $scope.amount === "0" ?  "False" : "True" }} </span>
Ризо
источник
1

Работает даже в экзотических ситуациях:

<br ng-show="myCondition == true" />
Steffomio
источник
0

Я добавлю мой в смесь:

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

это вычисляет оператор if один раз и не добавляет прослушивателя, но вы можете добавить дополнительный атрибут к элементу, который имеет set-if call wait-for = "somedata.prop", и он будет ждать, пока эти данные или свойство не будут установлены ранее оценивая оператор if один раз. этот дополнительный атрибут может быть очень полезен, если вы ожидаете данных из запроса 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
источник