Який найкращий спосіб умовно застосувати атрибути в AngularJS?


296

Мені потрібно вміти додати, наприклад, "contenteditable" до елементів, спираючись на булеву змінну на область застосування.

Приклад використання:

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

В результаті цього елемента буде додано contenteditable = true, якщо $scope.editModeвстановлено значення true. Чи є якийсь простий спосіб реалізувати такий ng-клас, як поведінка атрибутів? Я розглядаю можливість написання директиви та обміну, якщо ні.

Редагувати: я можу побачити, що між моєю запропонованою директивою attrs і ng-bind-attrs, можливо, є подібність , але вона була видалена в 1.0.0.rc3 , чому так?


2
Я нічого подібного не зустрічав. Я голосую, роби це! : D Можливо, подайте його на кутовий проект. Синтаксис, який краще відповідає ng-класу, було б добре. ng-attr="expression".
Xesued

Я напевно вважаю, що так!
Кеннет Лінн

3
Це насправді не те саме, що ngClass або ngStyle, оскільки вони керують одним атрибутом, і ви хочете керувати будь-яким атрибутом. Я думаю, було б краще створити contentEditableдирективу.
Джош Девід Міллер

@JoshDavidMiller +1 про це. Я думаю, що є невелика користь, щоб мати можливість контролювати будь-який атрибут, особливо враховуючи складність. Ви можете мати директиви, що умовно діють на змінну.
Umur Kontacı

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

Відповіді:


272

Я використовую наступне для умовного встановлення класу attr, коли ng-class не може бути використаний (наприклад, для стилю SVG):

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

129
Проблема такого підходу полягає в тому, що атрибут створюється незалежно від результату. В ідеалі ми хотіли б, щоб ми керували тим, чи атрибут не створюється взагалі.
airtonix

24
Зауважимо, що ng-attrment було вилучено з кута 1.2. Ця відповідь більше не діє.
Іуда Габріель Хіманго

2
Ви неправі. Цей проект github.com/codecapers/AngularJS-FlowChart використовує Angular 1.2 та ng-attr-. Також останні документи (кутовий 1.4) все ще включають ng-attr-
Ешлі Девіс

120

Ви можете префіксувати атрибути до, ng-attrщоб зрівняти кутовий вираз. Коли результат виразів не визначений, це вилучає значення з атрибута.

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

При використанні цього фокусу в директиві. Атрибути директиви будуть помилковими, якщо вони не мають значення.

Наприклад, сказане було б помилковим.

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 використовується прапор allOrNothing $ інтерполяту, тому якщо будь-яке вираження в інтерпольованій рядку призводить до невизначеності, атрибут видаляється та не додається до елемента."
Реаг.

9
Лише примітка для допомоги будь-яким майбутнім читачам, схоже, що “невизначена” поведінка була додана у Angular 1.3. Я використовую 1.2.27 і в даний час повинен IE8.
Адам Маршалл

3
Для підтвердження ще кутового 1.2.15 відображатиметься href, навіть якщо значення не визначене, схоже, що невизначена поведінка починається з кутового 1.3, як зазначено у вищезазначеному коментарі.
Брайан Огден

Важливо зауважити, що директива ng-attr-fooвсе одно завжди буде посилатися на fooдирективу, якщо вона існує, навіть ng-attr-fooоцінюється undefined. обговорення
обіймає

97

Я працював над цим, важко встановивши атрибут. І контроль застосовності атрибута, використовуючи булеве значення для атрибута.

Ось фрагмент коду:

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

Я сподіваюся, що це допомагає.


Оскільки кут може проаналізувати вираз IIF, то він ідеально підходить для оцінки стану в поточній області та призначення значень на основі цього стану.
mccainz

22

В останній версії Angular (1.1.5) вони включили умовну директиву під назвою ngIf. Він відрізняється від ngShowта ngHideтим, що елементи не приховані, але взагалі не включені до DOM. Вони дуже корисні для компонентів, які дорого створюються, але не використовуються:

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

32
Я вважаю, що ng-if працює лише на рівні елемента, тобто ви не можете вказати умовний лише один атрибут елемента.
Макс Стратер

3
Дійсно, але ви можете зробити це<h1 ng-if="editMode" contenteditable="true"><h1 ng-if="!editMode">
ByScripts

5
остерігайтеся, проте, це ng-ifстворює нову сферу.
Шимон Рахленко

1
@ShimonRachlenko Погодився! Це може бути великим джерелом плутанини та помилок. ng-ifстворює новий розмах, але ng-showне робить. Ця суперечливість завжди була для мене хворою. Реакція оборонного програмування на це: "завжди пов'язувати щось, що є крапкою у виразі", і це не буде проблемою.
Брайан Генісіо

Якщо ви хочете додати атрибут, який насправді є директивою, це чудово працює. Сором за дублювання коду
Адам Маршалл

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

Це має бути мені прийнятою відповіддю. Мій сценарій був<video ng-attr-autoplay="{{vm.autoplay || undefined}}" />
LucasM

6

Щодо прийнятого рішення - рішення, розміщеного Ешлі Девіс, описаний метод все ще друкує атрибут у DOM, незалежно від того, що значення, яке йому було призначено, не визначене.

Наприклад, у налаштуваннях поля введення як з ng-моделлю, так і з атрибутом значення:

<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 :)


При такому підході ви будете повторювати той самий код.
Кальян

Щоправда, але він зберігає декларацію моделі в безпеці. Моя проблема використання прийнятого рішення полягала в тому, що атрибут значення опинився в DOM, маючи перевагу над декларацією моделі. Отже, якщо атрибут значення порожній, але модель - ні, модель буде замінена, щоб прийняти порожнє значення.
alexc

6

Також ви можете використовувати такий вираз:

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

5

Я фактично написав патч, щоб зробити це кілька місяців тому (після того, як хтось запитав про це в #angularjs на freenode).

Він, ймовірно, не буде об’єднаний, але він дуже схожий на 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}}">

Це буде застосовуватися атрибут maxдо 100тільки , якщо discountTypeвизначається як%


1

Редагувати : Ця відповідь пов’язана з Angular2 +! Вибачте, я пропустив тег!

Оригінальна відповідь:

Що стосується дуже простого випадку, коли ви хочете застосувати (або встановити) атрибут лише якщо було встановлено певне значення введення, це так просто, як

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

Це те саме, що:

<my-element [conditionalAttr]="optionalValue ? 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" був встановлений лише тоді, коли атрибут кольору був там, інакше атрибут кольору у рядку "стилі" може бути використаний.

Звичайно, цього можна було б досягти і за допомогою

[style.color]="color" 

і

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

Angular.JS - це кутова 1, яка сильно відрізняється від Angular 2+. Ваше рішення відповідає для Angular 2+, але AngularJS (1) було запропоновано.
ssc-hrep3

@ ssc-hrep3: Ви праві. Вибачте, що я пропустив це! Дякую. Я відредагував відповідь, щоб вказати на це. :-)
Зафоїд

є angularjs не angular, angularjs is angular 1
dgzornoza

0

На всякий випадок, якщо вам потрібне рішення для Angular 2, то його просте, використовуйте прив'язку властивостей, як показано нижче, наприклад, ви хочете, щоб введення було прочитано лише умовно, а потім додайте в квадратні дужки аттрубу, а потім - знак та вираз.

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

є angularjs (angular1) не angular (angular2)
dgzornoza

кутовий 2+ і кутовий JS не однакові, вони більше схожі на різні вироби.
Санджай Сінгх

0

Вдалося це зробити:

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

Приємним є те, що якщо item.isSelected false, то атрибут просто не надається.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.