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


296

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

使用示例:

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

如果$scope.editMode设置为,将导致contenteditable = true被添加到元素true。有一些简单的方法可以实现这种ng-class这样的属性行为吗?我正在考虑编写指令,如果没有,请共享。

编辑: 我可以看到我提议的attrs指令和ng-bind-attrs之间似乎有些相似之处,但是在1.0.0.rc3中将其删除了,为什么呢?


2
我还没有遇到这样的事情。我投票去做!:D也许将其提交给有角项目。更好地匹配ng-class的语法会很好。ng-attr="expression"
Xesued

我一定会考虑的!
肯尼斯·林恩

3
这确实与ngClass或ngStyle不同,因为它们控制单个属性,而您想控制任何属性。我认为创建一个contentEditable指令会更好。
乔什·大卫·米勒

@JoshDavidMiller对此+1。我认为能够控制任何属性都有一点好处,尤其是考虑到复杂性。您可以使指令有条件地作用于变量。
UmurKontacı2013年

<h1 ng-attr-contenteditable="{{editMode && true : false}}">{{content.title}}</h1>
mia 2015年

Answers:


272

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

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

其他属性类型也应使用相同的方法。

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


97
只是为了弄清楚这个答案:如果您给加上任何属性前缀ng-attr-,则编译器将删除该前缀,并添加属性及其绑定到原始属性值的角度表达式结果的属性。
马提亚斯

12
我认为,如果您使用三元运算符,则更容易阅读,三元运算符已在1.1.5中添加了支持。看起来像:{{someConditionalExpression?'class-when-true':'class-when-false'}}
dshap 2014年

129
这种方法的问题在于,无论结果如何,都会创建属性。理想情况下,我们希望控制是否创建属性。
airtonix 2014年

24
请注意,ng-attr-东西已从Angular 1.2中删除。该答案不再有效。
Judah Gabriel Himango 2015年

2
你错了。这个项目github.com/codecapers/AngularJS-FlowChart使用Angular 1.2和ng-attr-。此外,最新文档(Angular 1.4)仍包含ng-attr-
Ashley Davis

120

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

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

会产生(当值为false时)

<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);
}

3
我喜欢这个答案。但是,我不认为如果值未定义,它将隐藏该属性。我可能会丢失一些东西。因此,第一个结果将是<a ng-attr-href="{{value || undefined}}"" href> Hello World </a>
Roman K

13
@RomanK您好,手册指出这undefined是一种特殊情况。“当使用ngAttr时,将使用$ interpolate的allOrNothing标志,因此,如果插值字符串中的任何表达式导致未定义,则该属性将被删除而不添加到元素中。”
Reactgular 2014年

9
只是为了帮助以后的读者注意,在Angular 1.3中似乎已添加了“未定义”行为。我正在使用1.2.27,目前必须是IE8。
亚当·马歇尔

3
为了确认更多的Angular 1.2.15即使值未定义也将显示href,就像上面的注释指出的那样,未定义的行为看起来像是在Angular 1.3中开始的。
布赖恩·奥格登

重要的是要注意,如果该指令存在,它ng-attr-foo仍将始终调用该foo指令,即使ng-attr-foo其结果为undefined讨论
拥抱

97

我通过硬设置属性来使它工作。然后使用属性的布尔值控制属性的适用性。

这是代码片段:

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

我希望这有帮助。


由于angular可以解析IIF表达式,因此非常适合评估当前范围内的状态并根据该状态辅助值。
mccainz 2015年

22

在最新版本的Angular(1.1.5)中,它们包括一个称为的条件指令ngIf。它是由不同ngShowngHide在的元素是不能隐藏,但不包括在所有的DOM。它们对于创建成本很高但不使用的组件非常有用:

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

32
我相信ng-if仅适用于元素级别,也就是说,您不能仅对元素的一个属性指定条件。
Max Strater 2014年

3
确实,但是您可以这样做<h1 ng-if="editMode" contenteditable="true"><h1 ng-if="!editMode">
ByScripts

5
但是要注意,这ng-if会创建新的作用域。
Shimon Rachlenko 2014年

1
@ShimonRachlenko同意!这可能是造成混乱和错误的重要原因。 ng-if创建一个新的作用域,但ng-show不会。这种矛盾一直是我的痛处。对此的防御性编程反应是:“始终绑定到表达式中点的东西”,这不会成为问题。
Brian Genisio 2014年

如果要添加实际上是指令的属性,则效果很好。对代码重复感到羞耻
亚当·马歇尔

16

为了使属性显示基于布尔检查的特定值,或者如果布尔检查失败则将其完全省略,我使用了以下方法:

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

用法示例:

<div ng-attr-class="{{params.type == 'test' ? 'itWasTest' : undefined }}">

将输出<div class="itWasTest"><div>基于的值params.type


9

<h1 ng-attr-contenteditable="{{isTrue || undefined }}">{{content.title}}</h1>

将在isTrue = true时产生: <h1 contenteditable="true">{{content.title}}</h1>

当isTrue = false时: <h1>{{content.title}}</h1>


5
如果我想要类似<h1 contenteditable =“ row”>之类的
东西怎么办

<h1 ng-attr-contenteditable="{{isTrue ? 'row' : undefined}}">{{content.title}} </h1>
PhatBuck

这应该是我接受的答案。我的情况是<video ng-attr-autoplay="{{vm.autoplay || undefined}}" />
LucasM '18

6

关于公认的解决方案(由Ashley Davis发布的解决方案),所描述的方法仍然会在DOM中打印属性,而不管分配给它的值是不确定的。

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

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

无论myValue背后是什么,价值属性仍然会在DOM中打印出来,从而得到解释。Ng模型然后被覆盖。

有点不愉快,但是使用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指令中使用更详细的检查方法:)


使用这种方法,您将尽管重复相同的代码。
Kalyan 2014年

是的,但是可以保证模型声明的安全。我使用可接受的解决方案的问题是value属性最终出现在DOM中,优先于模型声明。因此,如果value属性为空但模型不是,则模型将被覆盖以获取空值。
alexc 2014年

6

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

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

5

我实际上是在几个月前(在有人在freenode上的#angularjs中询问它之后)为此目的编写了一个补丁。

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

无论是否合并,现有的ng-attr- *都可能适合您的需求(正如其他人提到的那样),尽管它可能比您建议的更多ngClass样式的功能笨拙。


2

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

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

这将属性适用max100仅当discountType被定义为%


1

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

原始答案:

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

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

等同于:

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

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

示例:我有一种情况,我可以应用一种颜色,但也可以应用一种任意样式,其中color属性由于已经设置而无法使用(即使未提供@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;
...
}

因此,仅在出现color属性时才设置“ style.color”,否则可以使用“ styles”字符串中的color属性。

当然,这也可以通过

[style.color]="color" 

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

Angular.JS是Angular 1,它与Angular 2+完全不同。您的解决方案可以回答Angular 2+,但需要AngularJS(1)。
ssc-hrep3

@ ssc-hrep3:你是对的。对不起,我错过了!谢谢。我编辑了答案以指出这一点。:-)
Zaphoid

是angularjs不成角,angularjs是成角1
dgzornoza

0

万一您需要针对Angular 2的解决方案,然后使用其简单易用的属性绑定,如下所示,例如,您想使输入有条件地为只读,然后在方括号中添加attrbute,后跟=符号和表达式。

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

是angularjs(angular1)不是angular(angular2)
dgzornoza

angular 2+和Angular JS不一样,它们更像是完全不同的产品。
Sanjay Singh

0

能够做到这一点:

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

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

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.