Apa cara terbaik untuk menerapkan atribut secara kondisional di AngularJS?

296

Saya harus dapat menambahkan misalnya "contenteditable" ke elemen, berdasarkan pada variabel boolean pada lingkup.

Contoh penggunaan:

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

Akan menghasilkan contenteditable = true ditambahkan ke elemen jika $scope.editModedisetel ke true. Apakah ada cara mudah untuk mengimplementasikan perilaku atribut seperti ini? Saya sedang mempertimbangkan untuk menulis arahan dan berbagi jika tidak.

Sunting: Saya dapat melihat bahwa tampaknya ada beberapa kesamaan antara arahan attrs yang saya usulkan dan ng-bind-attrs, tetapi telah dihapus di 1.0.0.rc3 , mengapa demikian?

Kenneth Lynne
sumber
2
Saya belum menemukan hal seperti itu. Saya memilih melakukannya! : D Mungkin kirimkan ke proyek sudut. Sintaks yang lebih cocok dengan kelas ng akan lebih baik. ng-attr="expression".
Xesued
Saya pasti mempertimbangkan itu ya!
Kenneth Lynne
3
Ini sebenarnya tidak sama dengan ngClass atau ngStyle karena mereka mengontrol satu atribut dan Anda ingin mengontrol atribut apa pun . Saya pikir akan lebih baik untuk membuat contentEditablearahan.
Josh David Miller
@JoshDavidMiller +1 untuk itu. Saya pikir ada sedikit manfaat untuk dapat mengendalikan atribut apa pun, terutama mengingat kompleksitasnya. Anda dapat memiliki arahan yang berlaku pada suatu variabel.
Umur Kontacı
<h1 ng-attr-contenteditable="{{editMode && true : false}}">{{content.title}}</h1>
mia

Jawaban:

272

Saya menggunakan yang berikut ini untuk mengatur attr kelas secara kondisional ketika ng-class tidak dapat digunakan (misalnya saat menata SVG):

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

Pendekatan yang sama harus bekerja untuk tipe atribut lainnya.

(Saya pikir Anda harus menggunakan Angular terbaru yang tidak stabil untuk menggunakan ng-attr-, saya saat ini di 1.1.4)

Ashley Davis
sumber
97
Hanya untuk memperjelas jawaban ini: Jika Anda awalan atribut apa punng-attr- , maka kompiler akan menghapus awalan, dan menambahkan atribut dengan nilainya terikat pada hasil ekspresi sudut dari nilai atribut asli.
Matthias
12
Menurut pendapat saya, lebih mudah dibaca jika Anda menggunakan operator ternary, yang dukungannya ditambahkan pada 1.1.5. Itu akan terlihat seperti: {{someConditionalExpression? 'class-when-true': 'class-when-false'}}
dshap
129
masalah dengan pendekatan ini adalah bahwa atribut akan dibuat terlepas dari hasilnya. Idealnya kami ingin mengontrol apakah atribut akan dibuat atau tidak.
airtonix
24
Perhatikan bahwa hal-hal yang dihapus telah dihapus dari Angular 1.2. Jawaban ini tidak lagi valid.
Yehuda Gabriel Himango
2
Anda salah. Proyek ini github.com/codecapers/AngularJS-FlowChart menggunakan Angular 1.2 dan ng-attr-. Juga dokumen terbaru (Angular 1.4) masih menyertakan ng-attr-
Ashley Davis
120

Anda bisa mengawali atribut dengan ng-attruntuk eval ekspresi Angular. Ketika hasil dari ekspresi tidak terdefinisi, ini menghilangkan nilai dari atribut.

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

Akan menghasilkan (ketika nilai salah)

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

Jadi jangan gunakan falsekarena itu akan menghasilkan kata "false" sebagai nilainya.

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

Saat menggunakan trik ini dalam arahan. Atribut untuk arahan akan salah jika mereka kehilangan nilai.

Misalnya, hal di atas salah.

function post($scope, $el, $attr) {
      var url = $attr['href'] || false;
      alert(url === false);
}
Reactgular
sumber
3
Saya suka jawaban ini. Namun, saya tidak berpikir jika nilai tidak ditentukan itu akan menyembunyikan atribut. Tapi aku mungkin melewatkan sesuatu. Jadi hasil pertama adalah <a ng-attr-href="{{value || undefined}}"" href> Hello World </a>
Roman K
13
@RomanK hai, manual menyatakan itu undefinedadalah kasus khusus. "Saat menggunakan ngAttr, flag allOrNothing dari $ interpolate digunakan, jadi jika ekspresi apa pun dalam string yang diinterpolasi menghasilkan undefined, atribut dihapus dan tidak ditambahkan ke elemen."
Reactgular
9
Hanya sebuah catatan untuk membantu pembaca di masa mendatang, perilaku 'tidak terdefinisi' tampaknya telah ditambahkan dalam Angular 1.3. Saya menggunakan 1.2.27 dan saat ini harus IE8.
Adam Marshall
3
Untuk mengonfirmasi beberapa Angular 1.2.15 akan menampilkan href bahkan jika nilainya tidak terdefinisi, kelihatannya perilaku yang tidak terdefinisi dimulai dalam Angular 1.3 seperti yang dinyatakan dalam komentar di atas.
Brian Ogden
Penting untuk dicatat bahwa ng-attr-foomasih akan selalu menggunakan fooarahan jika ada, bahkan ng-attr-foodievaluasi undefined. diskusi
hughes
97

Saya mendapatkan ini bekerja dengan menetapkan atribut keras. Dan mengendalikan penerapan atribut menggunakan nilai boolean untuk atribut tersebut.

Berikut ini cuplikan kode:

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

Saya harap ini membantu.

jsbisht
sumber
Karena sudut dapat menguraikan ekspresi IIF ini berfungsi dengan baik untuk mengevaluasi keadaan dalam lingkup saat ini dan menilai nilai-nilai berdasarkan keadaan itu.
mccainz
22

Dalam versi terbaru Angular (1.1.5), mereka telah menyertakan arahan bersyarat yang disebut ngIf. Ini berbeda dari ngShowdan ngHidedalam elemen tidak tersembunyi, tetapi tidak termasuk dalam DOM sama sekali. Mereka sangat berguna untuk komponen yang mahal untuk dibuat tetapi tidak digunakan:

<h1 ng-if="editMode" contenteditable=true>{{content.title}}</h1>
Brian Genisio
sumber
32
Saya percaya ng-jika hanya bekerja pada tingkat elemen, yaitu, Anda tidak dapat menentukan syarat untuk hanya satu atribut elemen.
Max Strater
3
Memang, tetapi Anda kemudian dapat melakukannya<h1 ng-if="editMode" contenteditable="true"><h1 ng-if="!editMode">
ByScripts
5
waspadalah, bagaimanapun, itu ng-ifmenciptakan ruang lingkup baru.
Shimon Rachlenko
1
@ShimonRachlenko Setuju! Ini bisa menjadi sumber besar kebingungan dan bug. ng-ifmenciptakan ruang lingkup baru tetapi ng-showtidak. Ketidakkonsistenan ini selalu menjadi titik pahit bagi saya. Reaksi pemrograman defensif untuk ini adalah: "selalu mengikat sesuatu yang titik dalam ekspresi" dan itu tidak akan menjadi masalah.
Brian Genisio
Jika Anda ingin menambahkan atribut yang sebenarnya adalah arahan, ini berfungsi dengan baik. Malu tentang duplikasi kode
Adam Marshall
16

Untuk mendapatkan atribut untuk menunjukkan nilai tertentu berdasarkan pemeriksaan boolean, atau dihilangkan seluruhnya jika pemeriksaan boolean gagal, saya menggunakan yang berikut:

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

Contoh penggunaan:

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

Apakah output <div class="itWasTest">atau <div>berdasarkan nilaiparams.type

Lembah kecil
sumber
9

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

akan menghasilkan ketika isTrue = true: <h1 contenteditable="true">{{content.title}}</h1>

dan ketika isTrue = false: <h1>{{content.title}}</h1>

Garfi
sumber
5
bagaimana jika saya menginginkan sesuatu seperti <h1 contenteditable = "row">
SuperUberDuper
<h1 ng-attr-contenteditable="{{isTrue ? 'row' : undefined}}">{{content.title}} </h1>
PhatBuck
Ini seharusnya saya menjadi jawaban yang diterima. Skenario saya adalah<video ng-attr-autoplay="{{vm.autoplay || undefined}}" />
LucasM
6

Mengenai solusi yang diterima, yang diposting oleh Ashley Davis, metode yang dijelaskan masih mencetak atribut di DOM, terlepas dari kenyataan bahwa nilai yang telah ditetapkan tidak ditentukan.

Misalnya, pada pengaturan bidang input dengan model-ng dan atribut nilai:

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

Terlepas dari apa yang ada di balik myValue, atribut nilai masih dicetak di DOM, dengan demikian, ditafsirkan. Model-Ng kemudian, menjadi ditimpa.

Agak tidak menyenangkan, tetapi menggunakan ng-jika berhasil:

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

Saya akan merekomendasikan menggunakan cek lebih rinci di dalam arahan ng-if :)

alexc
sumber
Dengan pendekatan ini, Anda akan mengulang kode yang sama.
Kalyan
Benar, tetapi itu membuat deklarasi model aman. Masalah saya dengan menggunakan solusi yang diterima adalah bahwa atribut nilai berakhir di DOM, didahulukan dari deklarasi model. Jadi, jika atribut nilai kosong tetapi modelnya tidak, model akan diganti untuk mengambil nilai kosong.
alexc
6

Anda juga dapat menggunakan ekspresi seperti ini:

<h1 ng-attr-contenteditable="{{ editMode ? true : false }}"></h1>
Kamuran Sönecek
sumber
5

Saya benar-benar menulis tambalan untuk melakukan ini beberapa bulan yang lalu (setelah seseorang bertanya tentang hal itu di #angularjs di freenode).

Mungkin tidak akan digabung, tetapi sangat mirip dengan ngClass: https://github.com/angular/angular.js/pull/4269

Entah itu digabung atau tidak, hal-hal ng-attr- * yang ada mungkin cocok untuk kebutuhan Anda (seperti yang disebutkan orang lain), meskipun mungkin sedikit lebih janggal daripada fungsionalitas gaya ngClass yang Anda sarankan.

chronicsalsa
sumber
2

Untuk validasi bidang input dapat Anda lakukan:

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

Ini akan berlaku atribut maxuntuk 100hanya jika discountTypedidefinisikan sebagai%

Nestor Britez
sumber
1

Sunting : Jawaban ini terkait dengan Angular2 +! Maaf, saya melewatkan tag!

Jawaban asli:

Adapun kasus yang sangat sederhana ketika Anda hanya ingin menerapkan (atau mengatur) atribut jika nilai Input tertentu ditetapkan, semudah

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

Itu sama dengan:

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

(Jadi, opsional Nilai diterapkan jika diberikan sebaliknya ekspresi salah dan atribut tidak diterapkan.)

Contoh: Saya memiliki case, di mana saya membiarkan menerapkan warna tetapi juga gaya arbitrer, di mana atribut warna tidak berfungsi karena sudah diatur (bahkan jika @Input () warna tidak diberikan):

@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;
...
}

Jadi, "style.color" hanya disetel, ketika atribut warna ada di sana, jika tidak atribut warna dalam string "style" dapat digunakan.

Tentu saja, ini juga bisa dicapai dengan

[style.color]="color" 

dan

@Input color: (string | boolean) = false;
Zafoid
sumber
Angular.JS adalah Angular 1, yang sangat berbeda dari Angular 2+. Solusi Anda menjawab untuk Angular 2+, tetapi AngularJS (1) diminta.
ssc-hrep3
@ ssc-hrep3: Anda benar. Maaf saya melewatkannya! Terima kasih. Saya mengedit jawaban untuk menunjukkan hal itu. :-)
Zaphoid
adalah angularjs tidak angular, angularjs adalah angular 1
dgzornoza
0

Kalau-kalau Anda membutuhkan solusi untuk Angular 2 kemudian sederhana, gunakan properti mengikat seperti di bawah ini, misalnya Anda ingin membuat input hanya dibaca secara kondisional, kemudian tambahkan kurung kurawal di attrbute diikuti dengan = tanda dan ekspresi.

<input [readonly]="mode=='VIEW'"> 
Sanjay Singh
sumber
is angularjs (angular1) tidak angular (angular2)
dgzornoza
angular 2+ dan Angular JS tidak sama, mereka lebih seperti produk yang berbeda sama sekali.
Sanjay Singh
0

Mungkinkah ini berfungsi:

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

Yang menyenangkan di sini adalah bahwa jika item.isSelected adalah false maka atribut tidak dirender.

Richard Strickland
sumber