У меня проблема с попыткой использовать Angular *ngFor
и *ngIf
на том же элементе.
При попытке перебрать коллекцию в *ngFor
, коллекция рассматривается как null
и, следовательно, происходит сбой при попытке доступа к ее свойствам в шаблоне.
@Component({
selector: 'shell',
template: `
<h3>Shell</h3><button (click)="toggle()">Toggle!</button>
<div *ngIf="show" *ngFor="let thing of stuff">
{{log(thing)}}
<span>{{thing.name}}</span>
</div>
`
})
export class ShellComponent implements OnInit {
public stuff:any[] = [];
public show:boolean = false;
constructor() {}
ngOnInit() {
this.stuff = [
{ name: 'abc', id: 1 },
{ name: 'huo', id: 2 },
{ name: 'bar', id: 3 },
{ name: 'foo', id: 4 },
{ name: 'thing', id: 5 },
{ name: 'other', id: 6 },
]
}
toggle() {
this.show = !this.show;
}
log(thing) {
console.log(thing);
}
}
Я знаю, что простое решение состоит в том, чтобы переместиться на *ngIf
уровень выше, но для сценариев, таких как циклическое перемещение по элементам списка в a ul
, я бы в конечном итоге либо пуст, li
если коллекция пуста, либо мой li
s обернут в избыточные элементы контейнера.
Пример на этом плнкр .
Обратите внимание на ошибку консоли:
EXCEPTION: TypeError: Cannot read property 'name' of null in [{{thing.name}} in ShellComponent@5:12]
Я что-то не так делаю или это ошибка?
angular
ngfor
angular-ng-if
garethdn
источник
источник
Ответы:
Angular v2 не поддерживает более одной структурной директивы для одного и того же элемента.
В качестве обходного пути используйте
<ng-container>
элемент, который позволяет вам использовать отдельные элементы для каждой структурной директивы, но он не проставляется на DOM .<ng-template>
(<template>
до Angular v4) позволяет делать то же самое, но с другим синтаксисом, который сбивает с толку и больше не рекомендуетсяисточник
ngFor
на<ng-container>
элемент иngIf
на<div>
. Вы также можете иметь два вложенных<ng-container>
упаковки<div>
.<ng-container>
это просто вспомогательный элемент, который не будет добавлен в DOM.<ng-container>
. Он ведет себя так же, как и<template>
позволяет использовать «нормальный» синтаксис для структурных директив.Как все отметили, несмотря на то, что наличие нескольких шаблонных директив в одном элементе работает в Angular 1.x, в Angular 2 это не разрешено. Вы можете найти дополнительную информацию здесь: https://github.com/angular/angular/issues/ 7315
2016 угловой 2 бета
Решение заключается в использовании в
<template>
качестве заполнителя, поэтому код выглядит такно по какой-то причине выше не работает
2.0.0-rc.4
в этом случае вы можете использовать этоОбновленный ответ 2018
С обновлениями, прямо сейчас в 2018 году угловые v6 рекомендуют использовать
<ng-container>
вместо<template>
так вот обновленный ответ.
источник
Как упоминали @Zyzle и @ Günter в комментарии ( https://github.com/angular/angular/issues/7315 ), это не поддерживается.
С
нет пустых
<li>
элементов, когда список пуст. Даже<ul>
элемент не существует (как и ожидалось).Когда список заполнен, избыточные элементы контейнера отсутствуют.
Обсуждение GitHub (4792) , что @Zyzle упомянул в своем комментарии также представляет еще одно решение , используя
<template>
(ниже я использую исходную разметку - с помощью<div>
s):Это решение также не содержит каких-либо дополнительных / избыточных элементов контейнера.
источник
<template>
это способ добавить родительский элемент, который не будет отображаться в выводе.в формате HTML:
в css:
источник
Вы не можете иметь
ngFor
иngIf
на одном элементе. Что вы могли бы сделать, так это отложить заполнение массива, в котором вы используете,ngFor
до тех пор, пока в вашем примере не будет нажата кнопка переключения.Вот основной (не очень) способ, которым вы могли бы это сделать: http://plnkr.co/edit/Pylx5HSWIZ7ahoC7wT6P
источник
you can't
это не очень хороший ответ, вы согласны?Вы не можете использовать более одного
Structural Directive
в Angular для одного и того же элемента, это приводит к путанице и структуре, поэтому вам нужно применять их в 2 отдельных вложенных элемента (или вы можете использоватьng-container
), прочитайте это утверждение из команды Angular:Таким образом, вы можете использовать
ng-container
(Angular4) в качестве оболочки (будет удален из dom) или div или span, если у вас есть класс или некоторые другие атрибуты, как показано ниже:источник
Это будет работать, но элемент все еще будет в DOM.
источник
В таблице ниже перечислены только те элементы, для которых установлено значение «новичок». Требует и,
*ngFor
и*ngIf
для предотвращения нежелательных строк в HTML.Первоначально имел
*ngIf
и*ngFor
на том же<tr>
теге, но не работает. Добавлен<div>
в*ngFor
петлю и помещается*ngIf
в<tr>
тег, работает , как ожидалось.источник
<div>
внутренняя часть стола является идеей, особенно когда есть лучшие альтернативы. Вы проверяли, работает ли таким образом в IE, который особенно требователен к элементам<table>
Обновлено до angular2 beta 8
Теперь , как из angular2 бета-можно использовать
*ngIf
и*ngFor
на одном компоненте смотрите здесь .Alternate:
Иногда мы не можем использовать теги HTML внутри другого, например, in
tr
,th
(table
) или inli
(ul
). Мы не можем использовать другой тег HTML, но мы должны выполнить какое-то действие в той же ситуации, чтобы мы могли использовать тег HTML5<template>
таким образом.ngДля использования шаблона:
Если использовать шаблон:
Для получения дополнительной информации о структурных директивах angular2 смотрите здесь .
источник
источник
Вы также можете использовать
ng-template
(вместо шаблона. См. Примечание об использовании тега шаблона) для применения как * ngFor, так и ngIf к одному и тому же элементу HTML. Вот пример, где вы можете использовать как * ngIf, так и * ngFor для одного и того же элемента tr в угловой таблице.где
fruiArray = ['apple', 'banana', 'mango', 'pineapple']
.Замечания:
Предостережение использования только
template
тега вместоng-template
тега заключается в том, что он выбрасываетStaticInjectionError
в некоторых местах.источник
источник
Вы не можете использовать несколько структурных директив для одного элемента. Оберните ваш элемент
ng-template
и используйте там одну структурную директивуисточник
Вы можете сделать это по-другому, проверив длину массива
источник
app.component.ts
app.component.html
Вывод
источник