Visão geral da diretiva Angular Virtual ForOf
A diretiva igxForOf Ignite UI for Angular é uma alternativa ao ngForOf para criar modelos de grandes quantidades de dados. Ela usa virtualização nos bastidores para otimizar a renderização do DOM e o consumo de memória.
Angular Virtual For Directive Example
Getting Started with Ignite UI for Angular Virtual ForOf Directive
Para começar a usar a diretiva igxFor
Ignite UI for Angular, primeiro você precisa instalar Ignite UI for Angular. Em um aplicativo Angular existente, digite o seguinte comando:
ng add igniteui-angular
Para obter uma introdução completa ao Ignite UI for Angular, leia o tópico de introdução.
O próximo passo é importar o IgxForOfModule
no seu arquivo app.module.ts.
// app.module.ts
import { IgxForOfModule } from 'igniteui-angular';
// import { IgxForOfModule } from '@infragistics/igniteui-angular'; for licensed package
@NgModule({
imports: [
...
IgxForOfModule,
...
]
})
export class AppModule {}
Como alternativa, a partir da 16.0.0
você pode importar o IgxForOfDirective
como uma dependência autônoma.
// home.component.ts
import { IgxForOfDirective } from 'igniteui-angular';
// import { IgxForOfDirective } from '@infragistics/igniteui-angular'; for licensed package
@Component({
selector: 'app-home',
template: `
<span #container>
<ng-template *igxFor="data"></ng-template>
</span>
`,
styleUrls: ['home.component.scss'],
standalone: true,
imports: [IgxForOfDirective]
})
export class HomeComponent {
public data: Employee [];
}
Agora que você importou o módulo Ignite UI for Angular Tree Grid ou as diretivas, você pode começar a usar a diretiva igxFor
.
Using the Angular Virtual ForOf
Agora que importamos o módulo ou diretiva, vamos começar com uma configuração básica do igxFor
que se vincula aos dados locais:
<span #container>
<ng-template *igxFor="data"></ng-template>
</span>
A propriedade de dados é uma matriz que fornece os objetos de dados usados para construir o DOM virtualizado.
Examples
A diretiva igxFor
pode ser usada para virtualizar os dados na vertical, na horizontal ou em ambas as direções.
A virtualização funciona de forma semelhante ao Paging, cortando os dados em pedaços menores que são trocados de uma viewport de contêiner enquanto o usuário rola os dados horizontalmente/verticalmente. A diferença com o Paging é que a virtualização imita o comportamento natural da barra de rolagem. A diretiva igxFor
está criando contêineres roláveis e renderiza pequenos pedaços dos dados. Ela é usada dentro do igxGrid
e pode ser usada para construir uma igx-list
virtual.
Vertical virtualization
<igx-list>
<div [style.height]="'500px'" [style.overflow]="'hidden'" [style.position]="'relative'">
<igx-list-item [style.width]="'calc(100% - 18px)'"
*igxFor="let item of data | igxFilter: fo;
scrollOrientation : 'vertical';
containerSize: '500px';
itemSize: '50px'">
<div class="contact">
<span class="name">{{item.name}}</span>
</div>
</igx-list-item>
</div>
</igx-list>
Nota: É altamente recomendável que o contêiner pai do modelo igxForOf
tenha as seguintes regras CSS aplicadas: height
para vertical e width
para horizontal, overflow: hidden
e position: relative
. Isso ocorre porque o comportamento de rolagem suave é obtido por meio de deslocamentos de conteúdo que podem afetar visualmente outras partes da página se permanecerem visíveis.
Horizontal virtualization
<igx-list>
<div [style.width]="'880px'" [style.overflow]="'hidden'" [style.position]="'relative'">
<igx-list-item [style.width]="'220px'"
*igxFor="let item of data | igxFilter: fo;
scrollOrientation : 'horizontal';
containerSize: '880px';
itemSize: '220px'">
<div class="contact">
<span class="name">{{item.name}}</span>
</div>
</igx-list-item>
</div>
</igx-list>
Horizontal and vertical virtualization
<table #container [style.width]='width'
[style.height]='height'
[style.overflow]='"hidden"'
[style.position]='"relative"'>
<ng-template #scrollContainer igxFor let-rowData
[igxForOf]="data"
[igxForScrollOrientation]="'vertical'"
[igxForContainerSize]='height'
[igxForItemSize]='"50px"'>
<tr [style.display]="'flex'" [style.height]="'50px'">
<ng-template #childContainer igxFor let-col
[igxForOf]="cols"
[igxForScrollOrientation]="'horizontal'"
[igxForScrollContainer]="parentVirtDir"
[igxForContainerSize]='width'>
<td [style.min-width]='col.width + "px"'>
{{rowData[col.field]}}
</td>
</ng-template>
</tr>
</ng-template>
</table>
A diretiva igxFor
é usada para virtualizar dados nas direções vertical e horizontal dentro do igxGrid
.
Siga o tópico Virtualização de grade para obter informações e demonstrações mais detalhadas.
igxFor bound to remote service
A diretiva igxForOf
pode ser vinculada a um serviço remoto usando a propriedade Observable
-remoteData
(no caso a seguir). O evento chunkLoading
também deve ser utilizado para disparar as solicitações de dados.
<div style='height: 500px; overflow: hidden; position: relative;'>
<ng-template igxFor let-item [igxForOf]="remoteData | async"
(chunkPreload)="chunkLoading($event)"
[igxForScrollOrientation]="'vertical'"
[igxForContainerSize]='"500px"'
[igxForItemSize]='"50px"'
[igxForRemote]='true'
let-rowIndex="index" #virtDirRemote>
<div style='height:50px;'>{{item.ProductID}} : {{item.ProductName}}</div>
</ng-template>
</div>
Observação: há um requisito para definir a propriedade totalItemCount
na instância de igxForOf
.
this.virtDirRemote.totalItemCount = data['@odata.count'];
Para acessar a instância da diretiva do componente, ela deve ser marcada como ViewChild
:
@ViewChild('virtDirRemote', { read: IgxForOfDirective })
public virtDirRemote: IgxForOfDirective<any>;
Após a solicitação de carregamento do primeiro bloco, o totalItemCount
pode ser definido:
public ngAfterViewInit() {
this.remoteService.getData(this.virtDirRemote.state, (data) => {
this.virtDirRemote.totalItemCount = data['@odata.count'];
});
}
Ao solicitar dados, você pode aproveitar a interface IgxForOfState
, que fornece as propriedades startIndex
e chunkSize
. Observe que inicialmente o chunkSize será 0, então você tem que especificar o tamanho do primeiro chunk carregado (o melhor valor é o igxForContainerSize
inicial dividido pelo igxForItemSize
).
public getData(data?: IForOfState, cb?: (any) => void): any {
var dataState = data;
return this.http
.get(this.buildUrl(dataState))
.map((response) => response.json())
.map((response) => {
return response;
})
.subscribe((data) => {
this._remoteData.next(data.value);
if (cb) {
cb(data);
}
});
}
private buildUrl(dataState: any): string {
let qS: string = '?', requiredChunkSize: number;
if (dataState) {
const skip = dataState.startIndex;
requiredChunkSize = dataState.chunkSize === 0 ?
// Set initial chunk size, the best value is igxForContainerSize
// initially divided by igxForItemSize
10 : dataState.chunkSize;
const top = requiredChunkSize;
qS += `$skip=${skip}&$top=${top}&$count=true`;
}
return `${this.url}${qS}`;
}
Toda vez que o evento chunkPreload
é lançado, um novo bloco de dados deve ser solicitado:
chunkLoading(evt) {
if(this.prevRequest){
this.prevRequest.unsubscribe();
}
this.prevRequest = this.remoteService.getData(evt, ()=> {
this.virtDirRemote.cdr.detectChanges();
});
}
Local Variables
A diretiva igxFor
inclui as seguintes propriedades auxiliares em seu contexto: even
, odd
, first
e last
. Elas são usadas para identificar a posição atual do elemento na coleção. O seguinte trecho de código demonstra como usar a propriedade even
em um ng-template
. Uma classe even
será atribuída a cada elemento div even :
<ng-template igxFor let-item let-isEven="even"
[igxForOf]="data"
[igxForScrollOrientation]="'vertical'" >
<div [ngClass]="{even: isEven}"></div>
</ng-template>
Known Limitations
Limitação | Descrição |
---|---|
scrollTo o método não funciona corretamente quando o tamanho do conteúdo dos modelos renderizados muda após a inicialização |
Quando os elementos dentro do modelo têm um tamanho que muda o tempo de execução após a inicialização (por exemplo, como resultado da projeção de conteúdo, resolução de solicitação remota etc.), então oscrollTo o método não conseguirá rolar para o índice correto. O método rolará para a posição do índice antes que a alteração do tamanho do tempo de execução ocorra, portanto, o local não estará correto depois que o tamanho for alterado posteriormente. Uma possível solução alternativa é usar modelos que não alterem seu tamanho com base em seu conteúdo se o conteúdo for carregado posteriormente. |