在 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。我认为能够控制任何属性都有一点好处,尤其是考虑到复杂性。您可以让指令有条件地作用于变量。
<h1 ng-attr-contenteditable="editMode && true : false">content.title</h1>
【参考方案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
的条件指令。它与ngShow
和ngHide
的不同之处在于元素不是隐藏的,而是根本不包含在DOM 中。它们对于创建成本高但不使用的组件非常有用:
<h1 ng-if="editMode" contenteditable=true>content.title</h1>
【讨论】:
我相信 ng-if 仅适用于元素级别,也就是说,您不能仅对元素的一个属性指定条件。 确实如此,但你可以这样做<h1 ng-if="editMode" contenteditable="true"><h1 ng-if="!editMode">
但请注意,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】:<h1 ng-attr-contenteditable="isTrue || undefined ">content.title</h1>
将在 isTrue=true 时产生:
<h1 contenteditable="true">content.title</h1>
当 isTrue=false 时:
<h1>content.title</h1>
【讨论】:
如果我想要像 这样的东西怎么办<h1 ng-attr-contenteditable="isTrue ? 'row' : undefined">content.title </h1>
这应该是我接受的答案。我的场景是<video ng-attr-autoplay="vm.autoplay || undefined" />
【参考方案8】:
为了获得一个基于布尔检查显示特定值的属性,或者如果布尔检查失败则完全省略,我使用了以下内容:
ng-attr-example="params.type == 'test' ? 'itWasTest' : undefined "
示例用法:
<div ng-attr-class="params.type == 'test' ? 'itWasTest' : undefined ">
将根据params.type
的值输出<div class="itWasTest">
或<div>
【讨论】:
【参考方案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 中有条件地应用属性的最佳方法是啥?的主要内容,如果未能解决你的问题,请参考以下文章