在 AngularJS 中有条件地应用属性的最佳方法是啥?

Posted

技术标签:

【中文标题】在 AngularJS 中有条件地应用属性的最佳方法是啥?【英文标题】: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; 【参考方案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 的计算结果为 undefined。 discussion【参考方案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,则该属性根本不会被渲染。

【讨论】:

以上是关于在 AngularJS 中有条件地应用属性的最佳方法是啥?的主要内容,如果未能解决你的问题,请参考以下文章

如何在AngularJS网格中有条件地将列更改为文本框?

在 Facelets 中有条件地呈现纯 HTML 属性

如何在 Svelte 3 中有条件地添加和删除`use:`属性?

在 React.js 中有条件地设置 html 属性

属性的vue.js条件渲染[重复]

angularjs中的条件ng-include