AngularJSで属性を条件付きで適用する最良の方法は何ですか?


296

スコープのブール変数に基づいて、たとえば「contenteditable」を要素に追加できるようにする必要があります。

使用例:

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

$scope.editModeに設定されてtrueいる場合、要素にcontenteditable = trueが追加されます。このng-classのような属性動作を実装する簡単な方法はありますか?ディレクティブを書いて、そうでない場合は共有することを検討しています。

編集: 私が提案したattrsディレクティブとng-bind-attrsの間にいくつかの類似点があるように見えますが、それは1.0.0.rc3削除されました、なぜそうですか?


2
私はそのようなものに遭遇したことがありません。投票してください!:D多分それを角度のプロジェクトに提出してください。ng-classによりよく一致する構文が良いでしょう。ng-attr="expression"
Xesued 2013年

私は間違いなくそうだと考えています!
Kenneth Lynne 2013年

3
単一の属性を制御していて、任意の属性を制御したいので、これは実際にはngClassまたはngStyleと同じではありません。contentEditableディレクティブを作成した方がいいと思います。
Josh David Miller

@JoshDavidMiller +1。特に複雑さを考えると、属性を制御できることには少しメリットがあると思います。変数に対して条件付きで動作するディレクティブを持つことができます。
UmurKontacı2013年

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

回答:


272

ng-classを使用できない場合(たとえば、SVGをスタイリングする場合)、クラスattrを条件付きで設定するために以下を使用しています:

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

同じアプローチが他の属性タイプでも機能するはずです。

(ng-attr-を使用するには、最新の不安定なAngularを使用する必要があると思います。現在1.1.4を使用しています)


97
ただ、この答えを明確にする:あなたは接頭辞場合は任意の持つ属性をng-attr-、コンパイラは、プレフィックスを除去し、そのと属性を追加しますの結果にバインドされた角度の表現の元の属性値から。
Matthias

12
私の意見では、1.1.5でサポートが追加された3項演算子を使用すると読みやすくなります。それは次のようになります:{{someConditionalExpression?'class-when-true': 'class-when-false'}}
dshap

129
このアプローチの問題は、結果に関係なく属性が作成されることです。理想的には、属性が作成されるかどうかを制御する必要があります。
airtonix 2014年

24
ng-attr-stuffはAngular 1.2から削除されました。この回答は無効になりました。
ユダガブリエルヒマンゴ2015年

2
あなたは間違っている。このプロジェクトgithub.com/codecapers/AngularJS-FlowChartは、Angular 1.2とng-attr-を使用しています。また、最新のドキュメント(Angular 1.4)にはng-attr-がまだ含まれています
Ashley Davis

120

ng-attrAngular式を評価するために属性の前に付けることができます。式の結果が未定義の場合、これにより属性から値が削除されます。

<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になります。

たとえば、上記は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意志まだ常にたinvoke fooが存在する場合ディレクティブ、さえng-attr-fooに評価しますundefinedディスカッション
ヒューズ

97

属性をハード設定することでこれを機能させました。また、属性のブール値を使用して属性の適用性を制御します。

これがコードスニペットです。

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

これがお役に立てば幸いです。


angularはIIF式を解析できるため、これは現在のスコープの状態を評価し、その状態に基づいて値を割り当てるために完全に機能します。
mccainz

22

Angularの最新バージョン(1.1.5)では、と呼ばれる条件ディレクティブが含まれていますngIf。それは異なっているngShowngHide要素が隠されていないということではなく、すべてのDOMには含まれません。これらは作成にコストがかかるが使用されないコンポーネントに非常に役立ちます。

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

32
ng-ifは要素レベルでのみ機能する、つまり、要素の1つの属性だけに条件を指定することはできないと思います。
Max Strater 2014年

3
確かに、しかしあなたはそうすることができます<h1 ng-if="editMode" contenteditable="true"><h1 ng-if="!editMode">
ByScripts '16

5
ただし、ng-if新しいスコープが作成されることに注意してください。
Shimon Rachlenko 14

1
@ShimonRachlenko同意しました!これは、混乱とバグの大きな原因となる可能性があります。 ng-if新しいスコープを作成しますが、作成ng-showしません。この矛盾は常に私にとって痛い目に遭っています。これに対する防御的なプログラミングの反応は、「常に表現内のドットの何かにバインドする」ことであり、問​​題にはなりません。
Brian Genisio 14

実際にディレクティブである属性を追加する場合、これはうまく機能します。コードの重複についての恥
Adam Marshall

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">のようなものが必要な場合
SuperUberDuper

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

これは私が受け入れられる答えになるはずです。私のシナリオは<video ng-attr-autoplay="{{vm.autoplay || undefined}}" />
LucasM

6

承認されたソリューション(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ディレクティブ内でより詳細なチェックを使用することをお勧めします:)


このアプローチでは、同じコードを繰り返すことになります。
カリヤン14

真ですが、モデル宣言を安全に保ちます。受け入れられたソリューションの使用に関する私の問題は、value属性がDOMになり、モデル宣言よりも優先されることでした。したがって、value属性が空でモデルが空でない場合、モデルはオーバーライドされて空の値を取得します。
alexc 2014


5

私は実際にこれを行うパッチを数か月前に書きました(誰かがfreenodeの#angularjsでそれについて尋ねた後)。

おそらくマージされませんが、ngClassに非常に似ています:https : //github.com/angular/angular.js/pull/4269

それがマージされるかどうかにかかわらず、既存のng-attr- *のものはおそらくあなたのニーズに適しています(他の人が述べたように)。


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

(したがって、オプションの値が指定されている場合は適用されます。そうでない場合、式はfalseになり、属性は適用されません。)

例:色だけでなく任意のスタイルも適用できる場合がありました。(@ Input()色が指定されていなくても)color属性がすでに設定されているため機能しませんでした。

@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」は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'"> 

is angularjs(angular1)not angular(angular2)
dgzornoza

Angular 2+とAngular JSは同じではなく、まったく異なる製品のようです。
サンジャイシン

0

これを機能させることができました:

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

ここでの良い点は、item.isSelectedがfalseの場合、属性が単にレンダリングされないことです。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.