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

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

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

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

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

Каков рекомендуемый способ в angular условно показать и скрыть встроенный контент в angular только с помощью {{}}, а не обернуть содержимое в тегах html?

Ответ 1

EDIT: ответ 2Toad ниже - это то, что вы ищете! Подвиньте эту вещь

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

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

Здесь фильтр, который будет делать "немедленное, если" (aka iif):

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

и может использоваться следующим образом:

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

Ответ 2

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

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

Ответ 3

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

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

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

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

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

ng-show и ng-hide, конечно:

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

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

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

Ответ 4

Я использую следующее, чтобы условно установить класс 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

Ответ 5

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

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

Ответ 6

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

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

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

<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';
}

Ответ 7

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

Пример: Поддержка в angular UI upto ui 1.1.4

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

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

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

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

Ответ 8

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

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

Ответ 9

Я выброшу в микс:

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

это оценивает оператор if один раз и не добавляет прослушиватель часов, но вы можете добавить дополнительный атрибут к элементу с именем set-if, называемым 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');
              });
            }
          }
        };
      }
    };
  });

Ответ 10

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

Это работает для меня, как OP, говоря {{myVar === "two" ? "it true" : "it false"}}

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