AngularJS 模板中的条件逻辑

Posted

技术标签:

【中文标题】AngularJS 模板中的条件逻辑【英文标题】:Conditional logic in AngularJS template 【发布时间】:2012-12-14 04:31:50 【问题描述】:

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

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

我已设置a 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>

如果函数/表达式的计算结果为 false,这些都会消失。

【问题讨论】:

我或多或少有同样的问题,我最终使用了 Angular UI 和他们的 UI-IF 实现。它从 DOM 中删除了我想要的内容,因此问题得到了解决。更多信息在这里:angular-ui.github.com 【参考方案1】:

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

<div class="from" ng-show="message.from">From: message.from.name</div>

【讨论】:

我相信 ng-hide 只是设置 display:none,它不会从 DOM 中删除任何内容。 另外,在您的示例中,“createdBy”仍会显示,即使“from”正在显示。如果没有发件人地址,它应该只显示“createdBy”。 是的,它不会从 dom 中删除元素。对于 createdBy hide when from is there,只需在条件中添加条件:jsfiddle.net/pGwRu/3【参考方案2】:

您可以使用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>

如果您不希望 DOM 加载空 div,则需要使用 $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()
      
   ;
);

【讨论】:

我尽我所能使用 ng-switch 创建了一个新的小提琴 - jsfiddle.net/jon64digital/pGwRu/5 - 但是,我认为它不会工作,原因有几个。 (1) -when="" 似乎不适用于检查属性是否丢失。 (2) 即使它确实如此,我相信 DOM 仍然会被空的 div 和额外的包装 div 乱扔。 我还不够先进,无法编写自己的指令,但本能地感觉使用 ajax 调用来获取模板是错误的。是否可以在 HTML 中包含模板(在指令内)?我猜这个表达式将是指令标签上的一个属性(它可以调用一个函数)。如果表达式评估为 true,则内部模板将被绑定并显示,如果表达式评估为 false,则该元素将从 DOM 中删除。 您也可以使用硬编码模板(字符串),是的。但那样它的可重用性就会降低。 我刚刚被指向 Angular UI IF 指令的方向。它看起来像是我需要的,但我不明白它是如何工作的,所以当我不明白它在做什么时,我总是小心翼翼地在我的项目中包含一些东西。 Asgoth,我不是在谈论在指令的 JS 代码中对模板进行硬编码。我的意思是把它放在指令的外部标签之间,例如模板放在这里.【参考方案3】:

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

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

1.1.5还引入了ternary operator ng-switch 可用于有条件地从 DOM 中添加/删除元素 另见How do I conditionally apply CSS styles in AngularJS?

原答案:

这是一个不太好的“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>

Fiddle.

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

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

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

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

【讨论】:

谢谢马克,我可能会使用 UI-IF,因为你说的原因,它可能是最防弹的方法。但是,我查看了 ui-if 的代码,它做了很多我不理解的事情,而且我总是对使用我不理解的代码感到紧张。 我刚刚注意到虽然 ui-if 不会替换自己,但它仍然会在我的模板周围留下一个包装 div。大概它出于某种原因必须这样做,与想要保持对表达式的关注有关?

以上是关于AngularJS 模板中的条件逻辑的主要内容,如果未能解决你的问题,请参考以下文章

AngularJS 模板中的内联逻辑

在 Jinja 模板中使用条件逻辑处理用户选择(凯撒密码 Django Web 应用程序)

回溯模板

Docusign 中的条件逻辑

AngularJS 模板中的 if else 语句

C# 中的逻辑和条件 AND、OR 有啥区别? [复制]