【问题标题】:What is the best way to conditionally apply attributes in AngularJS?在 AngularJS 中有条件地应用属性的最佳方法是什么?
【发布时间】:2013-03-19 18:02:09
【问题描述】:

我需要能够基于作用域上的布尔变量向元素添加例如“contenteditable”。

使用示例:

<h1 attrs="{'contenteditable=\"true\"': editMode}">{{content.title}}</h1>

如果 $scope.editMode 设置为 true,将导致 contenteditable=true 添加到元素中。 有没有一些简单的方法来实现这个类似 ng-class 的属性行为?如果没有,我正在考虑写一个指令并分享。

编辑: 我可以看到我提出的 attrs 指令和ng-bind-attrs, but it was removed in 1.0.0.rc3 之间似乎有一些相似之处,为什么会这样?

【问题讨论】:

  • 我没有遇到过这样的事情。我投票去做! :D 也许将它提交给 Angular 项目。更好地匹配 ng-class 的语法会很好。 ng-attr="expression".
  • 我肯定认为是的!
  • 这确实与 ngClass 或 ngStyle 不同,因为它们控制 single 属性,而您想要控制 any 属性。我认为创建一个contentEditable 指令会更好。
  • @JoshDavidMiller 对此 +1。我认为能够控制任何属性都有一点好处,尤其是考虑到复杂性。您可以让指令有条件地作用于变量。
  • &lt;h1 ng-attr-contenteditable="{{editMode &amp;&amp; true : false}}"&gt;{{content.title}}&lt;/h1&gt;

标签: angularjs angularjs-directive


【解决方案1】:

当无法使用 ng-class 时(例如在设置 SVG 样式时),我正在使用以下有条件地设置类属性:

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

同样的方法应该适用于其他属性类型。

(我认为您需要使用最新的不稳定 Angular 才能使用 ng-attr-,我目前使用的是 1.1.4)

【讨论】:

  • 只是为了澄清这个答案:如果您在 any 属性前加上 ng-attr-,那么编译器将去掉前缀,并添加属性及其 value 从原始属性值绑定到 角度表达式 的结果。
  • 在我看来,如果你使用三元运算符,它会更容易阅读,在 1.1.5 中添加了对它的支持。这看起来像: {{ someConditionalExpression ? 'class-when-true' : 'class-when-false' }}
  • 这种方法的问题是无论结果如何都会创建属性。理想情况下,我们希望控制属性是否被创建。
  • 请注意,ng-attr-stuff 已从 Angular 1.2 中删除。此答案不再有效。
  • 你错了。这个项目github.com/codecapers/AngularJS-FlowChart 使用 Angular 1.2 和 ng-attr-。最新的文档(Angular 1.4)仍然包括 ng-attr-
【解决方案2】:

在最新版本的 Angular (1.1.5) 中,它们包含了一个名为 ngIf 的条件指令。它与ngShowngHide 的不同之处在于元素不是隐藏的,而是根本不包含在DOM 中。它们对于创建成本高但不使用的组件非常有用:

<h1 ng-if="editMode" contenteditable=true>{{content.title}}</h1>

【讨论】:

  • 我相信 ng-if 仅适用于元素级别,也就是说,您不能仅对元素的一个属性指定条件。
  • 确实如此,但你可以这样做&lt;h1 ng-if="editMode" contenteditable="true"&gt;&lt;h1 ng-if="!editMode"&gt;
  • 但请注意,ng-if 会创建一个新范围。
  • @ShimonRachlenko 同意!这可能是混乱和错误的一大来源。 ng-if 创建一个新范围,但 ng-show 没有。这种矛盾一直是我的痛处。对此的防御性编程反应是:“总是绑定到表达式中的点”,这不会成为问题。
  • 如果你想添加一个实际上是指令的属性,这很好用。对代码重复感到羞耻
【解决方案3】:

实际上几个月前我写了一个补丁来做到这一点(在有人在 freenode 上的#angularjs 中询问它之后)。

它可能不会被合并,但它与ngClass非常相似:https://github.com/angular/angular.js/pull/4269

无论是否合并,现有的 ng-attr-* 东西可能都适合您的需求(正如其他人所提到的),尽管它可能比您建议的更多 ngClass 风格的功能有点笨拙.

【讨论】:

    【解决方案4】:

    关于已接受的解决方案,即 Ashley Davis 发布的解决方案,所描述的方法仍然会在 DOM 中打印属性,而不管分配给它的值是未定义的事实。

    例如,在具有 ng-model 和 value 属性的输入字段设置上:

    <input type="text" name="myInput" data-ng-attr-value="{{myValue}}" data-ng-model="myModel" />
    

    不管 myValue 后面是什么,value 属性仍然会打印在 DOM 中,因此会被解释。然后,Ng-model 被覆盖。

    有点不愉快,但使用 ng-if 可以解决问题:

    <input type="text" name="myInput" data-ng-if="value" data-ng-attr-value="{{myValue}}" data-ng-model="myModel" />
    <input type="text" name="myInput" data-ng-if="!value" data-ng-model="myModel" />
    

    我建议在 ng-if 指令中使用更详细的检查:)

    【讨论】:

    • 使用这种方法,您将重复相同的代码。
    • 是的,但它保证了模型声明的安全。我使用公认解决方案的问题是 value 属性最终出现在 DOM 中,优先于模型声明。因此,如果 value 属性为空但模型不是,则模型将被覆盖以获取空值。
    【解决方案5】:

    您可以在属性前面加上 ng-attr 来评估 Angular 表达式。当表达式的结果未定义时,这会从属性中删除值。

    <a ng-attr-href="{{value || undefined}}">Hello World</a>
    

    将产生(当值为假时)

    <a ng-attr-href="{{value || undefined}}" href>Hello World</a>
    

    所以不要使用false,因为这会产生单词“false”作为值。

    <a ng-attr-href="{{value || false}}" href="false">Hello World</a>
    

    在指令中使用此技巧时。如果缺少值,指令的属性将为 false。

    例如,上面是错误的。

    function post($scope, $el, $attr) {
          var url = $attr['href'] || false;
          alert(url === false);
    }
    

    【讨论】:

    • 我喜欢这个答案。但是,我认为如果 value 未定义,它不会隐藏该属性。不过,我可能会遗漏一些东西。所以第一个结果是 Hello World
    • @RomanK 嗨,手册指出undefined 是一个特例。 “在使用ngAttr时,使用了$interpolate的allOrNothing标志,所以如果插值字符串中的任何表达式导致undefined,该属性将被移除,而不是添加到元素中。”
    • 只是一个注释以帮助任何未来的读者,“未定义”行为似乎已添加到 Angular 1.3 中。我使用的是 1.2.27,目前必须 IE8。
    • 为了确认更多 Angular 1.2.15 将显示 href 即使值未定义,看起来未定义的行为从 Angular 1.3 开始,如上述评论所述。
    • 请务必注意,ng-attr-foo 仍将始终调用 foo 指令(如果存在),即使 ng-attr-foo 的计算结果为 undefineddiscussion
    【解决方案6】:

    我通过努力设置属性来完成这项工作。并使用属性的布尔值控制属性的适用性。

    这里是sn-p的代码:

    <div contenteditable="{{ condition ? 'true' : 'false'}}"></div>
    

    我希望这会有所帮助。

    【讨论】:

    • 由于 Angular 可以解析 IIF 表达式,因此非常适合评估当前范围内的状态并根据该状态分配值。
    【解决方案7】:

    &lt;h1 ng-attr-contenteditable="{{isTrue || undefined }}"&gt;{{content.title}}&lt;/h1&gt;

    将在 isTrue=true 时产生: &lt;h1 contenteditable="true"&gt;{{content.title}}&lt;/h1&gt;

    当 isTrue=false 时: &lt;h1&gt;{{content.title}}&lt;/h1&gt;

    【讨论】:

    • 如果我想要像

      这样的东西怎么办
    • &lt;h1 ng-attr-contenteditable="{{isTrue ? 'row' : undefined}}"&gt;{{content.title}} &lt;/h1&gt;
    • 这应该是我接受的答案。我的场景是&lt;video ng-attr-autoplay="{{vm.autoplay || undefined}}" /&gt;
    【解决方案8】:

    为了获得一个基于布尔检查显示特定值的属性,或者如果布尔检查失败则完全省略,我使用了以下内容:

    ng-attr-example="{{params.type == 'test' ? 'itWasTest' : undefined }}"

    示例用法:

    &lt;div ng-attr-class="{{params.type == 'test' ? 'itWasTest' : undefined }}"&gt;

    将根据params.type 的值输出&lt;div class="itWasTest"&gt;&lt;div&gt;

    【讨论】:

      【解决方案9】:

      你也可以使用这样的表达式:

      <h1 ng-attr-contenteditable="{{ editMode ? true : false }}"></h1>
      

      【讨论】:

        【解决方案10】:

        对于输入字段验证,您可以执行以下操作:

        <input ng-model="discount" type="number" ng-attr-max="{{discountType == '%' ? 100 : undefined}}">
        

        仅当 discountType 定义为 % 时,才会将属性 max 应用于 100

        【讨论】:

          【解决方案11】:

          如果您需要 Angular 2 的解决方案,那么它很简单,使用如下属性绑定,例如你想让输入有条件地只读,然后在方括号中添加属性,然后是 = 符号和表达式。

          <input [readonly]="mode=='VIEW'"> 
          

          【讨论】:

          • 是 angularjs (angular1) 不是 angular (angular2)
          • angular 2+ 和 Angular JS 不一样,它们更像是完全不同的产品。
          【解决方案12】:

          编辑:这个答案与Angular2+有关!抱歉,我错过了标签!

          原答案:

          至于非常简单的情况,如果您只想应用(或设置)某个属性(如果设置了某个 Input 值),它就像

          <my-element [conditionalAttr]="optionalValue || false">
          

          同理:

          <my-element [conditionalAttr]="optionalValue ? optionalValue : false">
          

          (因此,如果给定,则应用 optionalValue,否则表达式为 false 并且不应用属性。)

          示例:我有一个案例,我让应用颜色但也应用任意样式,其中颜色属性不起作用,因为它已经设置(即使没有给出 @Input() 颜色):

          @Component({
            selector: "rb-icon",
            styleUrls: ["icon.component.scss"],
            template: "<span class="ic-{{icon}}" [style.color]="color==color" [ngStyle]="styleObj" ></span>",
          })
          export class IconComponent {
             @Input() icon: string;
             @Input() color: string;
             @Input() styles: string;
          
             private styleObj: object;
          ...
          }
          

          所以,“style.color”只有在有颜色属性时才被设置,否则可以使用“styles”字符串中的颜色属性。

          当然,这也可以通过

          来实现
          [style.color]="color" 
          

          @Input color: (string | boolean) = false;
          

          【讨论】:

          • Angular.JS 是 Angular 1,与 Angular 2+ 有很大不同。您的解决方案回答了 Angular 2+,但要求使用 AngularJS (1)。
          • @ssc-hrep3:你是对的。对不起,我错过了!谢谢。我编辑了答案以指出这一点。 :-)
          • 是 angularjs 不是 angular,angularjs 是 angular 1
          【解决方案13】:

          能够让这个工作:

          ng-attr-aria-current="{{::item.isSelected==true ? 'page' : undefined}}"
          

          这里的好处是,如果 item.isSelected 为 false,则该属性根本不会被渲染。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2017-01-19
            • 2017-11-28
            • 1970-01-01
            • 2016-05-23
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多