Estou tendo um problema ao tentar usar o Angular *ngFor
e *ngIf
no mesmo elemento.
Ao tentar fazer um loop pela coleção no *ngFor
, a coleção é vista como null
e, consequentemente, falha ao tentar acessar suas propriedades no modelo.
@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);
}
}
Eu sei que a solução mais fácil é *ngIf
subir de nível, mas para cenários como repetir itens de lista em um ul
, eu terminaria com um vazio li
se a coleção estiver vazia ou com meus li
elementos de contêiner redundantes.
Exemplo neste plnkr .
Observe o erro do console:
EXCEPTION: TypeError: Cannot read property 'name' of null in [{{thing.name}} in ShellComponent@5:12]
Estou fazendo algo errado ou isso é um bug?
angular
ngfor
angular-ng-if
garethdn
fonte
fonte
Respostas:
O Angular v2 não suporta mais de uma diretiva estrutural no mesmo elemento.
Como solução alternativa, use o
<ng-container>
elemento que permite usar elementos separados para cada diretiva estrutural, mas ele não é carimbado no DOM .<ng-template>
(<template>
antes do Angular v4) permite fazer o mesmo, mas com uma sintaxe diferente, que é confusa e não é mais recomendadafonte
ngFor
no<ng-container>
elemento engIf
no<div>
. Você também pode ter dois aninhada<ng-container>
envolvendo o<div>
.<ng-container>
é apenas um elemento auxiliar que não será adicionado ao DOM.<ng-container>
. Ele se comporta da mesma forma,<template>
mas permite usar a sintaxe "normal" para diretivas estruturais.Como todos apontaram, apesar de ter várias diretivas de modelo em um único elemento funcionar no angular 1.x, não é permitido no Angular 2. Você pode encontrar mais informações aqui: https://github.com/angular/angular/issues/ 7315
2016 angular 2 beta
solução é usar o
<template>
como um espaço reservado, para que o código fique assimmas, por algum motivo acima, não funciona.
2.0.0-rc.4
Nesse caso, você pode usar esteResposta atualizada 2018
Com atualizações, agora em 2018 a angular v6 recomenda usar em
<ng-container>
vez de<template>
então aqui está a resposta atualizada.
fonte
Como o @Zyzle mencionou, e o @ Günter mencionado em um comentário ( https://github.com/angular/angular/issues/7315 ), isso não é suportado.
Com
não há
<li>
elementos vazios quando a lista está vazia. Mesmo o<ul>
elemento não existe (como esperado).Quando a lista é preenchida, não há elementos de contêiner redundantes.
A discussão no github ( 4792) mencionada pelo @Zyzle em seu comentário também apresenta outra solução usando
<template>
(abaixo, estou usando sua marcação original - usando<div>
s):Essa solução também não apresenta nenhum elemento de contêiner extra / redundante.
fonte
<template>
é a maneira de adicionar um elemento pai que não será exibido na saída.em html:
em css:
fonte
Você não pode ter
ngFor
engIf
no mesmo elemento. O que você pode fazer é adiar o preenchimento da matriz em que você está usandongFor
até clicar no botão de alternância do seu exemplo.Aqui está uma maneira básica (não ótima) de fazê-lo: http://plnkr.co/edit/Pylx5HSWIZ7ahoC7wT6P
fonte
you can't
não é realmente uma boa resposta, você não concorda?Você não pode usar mais de um
Structural Directive
no Angular no mesmo elemento, isso cria uma confusão e estrutura ruins; portanto, você deve aplicá-los em 2 elementos aninhados separados (ou pode usarng-container
). Leia esta declaração da equipe do Angular:Portanto, você pode usar
ng-container
(Angular4) como o wrapper (será excluído do dom) ou um div ou span se você tiver classe ou alguns outros atributos, como abaixo:fonte
Isso funcionará, mas o elemento ainda estará no DOM.
fonte
A tabela abaixo lista apenas os itens que têm um valor "iniciante" definido. Requer o
*ngFor
e o*ngIf
para evitar linhas indesejadas em html.Originalmente tinha
*ngIf
e*ngFor
na mesma<tr>
tag, mas não funciona. Adicionado a<div>
para o*ngFor
loop e colocado*ngIf
na<tr>
tag, funciona conforme o esperado.fonte
<div>
dentro de uma mesa seja uma idéia de gosma, especialmente quando existem alternativas melhores. Você verificou se, portanto, funciona no IE, o que é especialmente exigente quanto aos elementos em #<table>
Atualizado para o angular2 beta 8
Agora, a partir do angular2 beta 8, podemos usar
*ngIf
e*ngFor
no mesmo componente, veja aqui .Alternar:
Às vezes, não podemos usar tags HTML dentro de outro, como in
tr
,th
(table
) ou inli
(ul
). Não podemos usar outra tag HTML, mas precisamos executar alguma ação na mesma situação para podermos usar a tag HTML5<template>
dessa maneira.ngPara usar o modelo:
ngSe usando o modelo:
Para mais informações sobre diretivas estruturais em angular2, veja aqui .
fonte
fonte
Você também pode usar
ng-template
(em vez de modelo. Consulte a nota sobre o uso da marca de modelo) para aplicar * ngFor e ngIf no mesmo elemento HTML. Aqui está um exemplo em que você pode usar * ngIf e * ngFor para o mesmo elemento tr na tabela angular.Onde
fruiArray = ['apple', 'banana', 'mango', 'pineapple']
.Nota:
A ressalva de usar apenas a
template
tag em vez dang-template
tag é que ela é lançadaStaticInjectionError
em alguns lugares.fonte
fonte
Você não pode usar várias diretivas estruturais no mesmo elemento. Envolva seu elemento
ng-template
e use uma diretiva estrutural láfonte
Você pode fazer isso de outra maneira, verificando o comprimento da matriz
fonte
app.component.ts
app.component.html
Resultado
fonte