71

我有一个看起来像这样的角度模板......

<div ng-repeat="message in data.messages" ng-class="message.type">

    <div class="info">
        <div class="type"></div>
        <div class="from">From Avatar</div>
        <div class="createdBy">Created By Avatar</div>
        <div class="arrowTo">
            <div class="arrow"></div>
            <div class="to">To Avatar</div>
        </div>
        <div class="date">
            <div class="day">25</div>
            <div class="month">Dec</div>
        </div>
    </div>

    <div class="main">
        <div class="content">
            <div class="heading2">{{message.title}}</div>
            <div ng-bind-html="message.content"></div>
        </div>

    </div>

    <br />
    <hr />
    <br />

</div>

我已经设置了一个 JSfiddle来显示正在绑定的数据。

我需要做的是根据数据内容有条件地显示“from”、“to”和“arrowTo”div。

日志是这样的...

  • 如果数据中有“from”对象,则显示“from”div 并绑定数据,但不显示“createdBy”div。
  • 如果没有“from”对象但有“createdBy”对象,则显示“createdBy”div 并绑定数据。
  • 如果数据中有“to”对象,则显示“arrowTo”div 并绑定它的数据。

或者用简单的英语,如果有发件人地址,则显示它,否则显示谁创建了记录,如果有收件人地址,则也显示。

我已经研究过使用 ng-switch 但我认为我必须添加额外的标记,如果没有数据,这将留下一个空的 div。另外,我需要嵌套 switch 指令,我不确定这是否可行。

有任何想法吗?

更新:

如果我要编写自己的指令(如果我知道怎么做!)那么这里有一些伪代码来展示我想如何使用它......

<div ng-if="showFrom()">
    From Template Goes Here
</div>
<div ng-if="showCreatedBy()">
    CreatedBy Template Goes Here
</div>
<div ng-if="showTo()">
    To Template Goes Here
</div>

如果函数/表达式评估为假,这些中的每一个都会消失。

4

3 回答 3

89

Angular 1.1.5 引入了ng-if指令。这是针对这个特定问题的最佳解决方案。如果您使用的是旧版本的 Angular,请考虑使用 angular-ui 的ui-if指令。

如果您来到这里寻找“模板中的条件逻辑”一般问题的答案,还请考虑:


原答案:

这是一个不太好的“ng-if”指令:

myApp.directive('ngIf', function() {
    return {
        link: function(scope, element, attrs) {
            if(scope.$eval(attrs.ngIf)) {
                // remove '<div ng-if...></div>'
                element.replaceWith(element.children())
            } else {
                element.replaceWith(' ')
            }
        }
    }
});

允许这种 HTML 语法:

<div ng-repeat="message in data.messages" ng-class="message.type">
   <hr>
   <div ng-if="showFrom(message)">
       <div>From: {{message.from.name}}</div>
   </div>    
   <div ng-if="showCreatedBy(message)">
      <div>Created by: {{message.createdBy.name}}</div>
   </div>    
   <div ng-if="showTo(message)">
      <div>To: {{message.to.name}}</div>
   </div>    
</div>

小提琴

replaceWith() 用于从 DOM 中删除不需要的内容。

此外,正如我在 Google+ 上提到的,如果您想使用 ng-show 而不是自定义指令,则可以使用ng-style有条件地加载背景图像。(为了其他读者的利益,Jon 在 Google+ 上说:“这两种方法都使用 ng-show,我试图避免,因为它使用 display:none 并在 DOM 中留下额外的标记。这是这种情况下的一个特殊问题,因为隐藏元素将有一个背景图像,该图像仍将在大多数浏览器中加载。”)。
另请参阅如何在 AngularJS 中有条件地应用 CSS 样式?

angular-ui ui-if指令监视 if 条件/表达式的变化。我的没有。因此,虽然我的简单实现会在模型发生更改以仅影响模板输出时正确更新视图,但如果条件/表达式答案发生更改,它将无法正确更新视图。

例如,如果模型中 from.name 的值发生变化,视图将更新。但是如果你delete $scope.data.messages[0].from,from 名称将从视图中删除,但模板不会从视图中删除,因为 if 条件/表达式没有被监视。

于 2012-12-29T22:34:06.040 回答
21

您可以使用ngSwitch指令:

  <div ng-switch on="selection" >
    <div ng-switch-when="settings">Settings Div</div>
    <span ng-switch-when="home">Home Span</span>
    <span ng-switch-default>default</span>
  </div>

如果您不希望使用空 div 加载 DOM,则需要使用 $http 创建自定义指令来加载(子)模板,并在达到特定条件时使用 $compile 将其注入 DOM。

这只是一个(未经测试的)示例。它可以而且应该被优化:

HTML:

<conditional-template ng-model="element" template-url1="path/to/partial1" template-url2="path/to/partial2"></div>

指示:

app.directive('conditionalTemplate', function($http, $compile) {
   return {
      restrict: 'E',
      require: '^ngModel',
      link: function(sope, element, attrs, ctrl) {
        // get template with $http
        // check model via ctrl.$viewValue
        // compile with $compile
        // replace element with element.replaceWith()
      }
   };
});
于 2012-12-29T10:51:22.503 回答
6

您可以在循环中的每个 div 元素上使用 ng-show。这是你想要的:http: //jsfiddle.net/pGwRu/2/

<div class="from" ng-show="message.from">From: {{message.from.name}}</div>
于 2012-12-29T00:42:08.357 回答