Web Components Grid Overview and Configuration

    The Ignite UI for Web Components Data Table / Data Grid is a tabular Web Components grid component that allows you to quickly bind and display your data with little coding or configuration. Features of the Web Components data grid in our toolbox include filtering, sorting, templates, row selection, row grouping, row pinning and movable columns.

    The Web Components tables are optimized for live streaming data, with the ability to handle unlimited data set size in a number of rows or columns.

    Web Components Data Grid

    Web Components Data Grid Example

    In this Ignite UI for Web Components Grid example, you can see how users can do both basic and excel-style filtering, live-data sorting, and use grid summaries as well as cell templating. The demo also includes paging set to display 10 items per page.

    Getting Started with Web Components Data Grid

    Dependencies

    To get started with the Web Components Data Grid, first you need to install the igniteui-webcomponents-grids package.

    npm install --save igniteui-webcomponents-grids
    

    You also need to include the following import to use the grid:

    import 'igniteui-webcomponents-grids/grids/combined.js';
    

    The corresponding styles should also be referenced. You can choose light or dark option for one of the themes and based on your project configuration to import it:

    import 'igniteui-webcomponents-grids/grids/themes/light/bootstrap.css';
    

    Or to link it:

    <link rel='stylesheet' href='node_modules/igniteui-webcomponents-grids/grids/themes/light/bootstrap.css'>
    

    For more details on how to customize the appearance of the grid, you may have a look at the styling section.

    Usage

    Agora que temos os pacotes de grade importados, vamos começar com a configuração básica e vincular aos dados locais:

    <igc-grid id="grid1" auto-generate="true"></igc-grid>
    
    constructor() {
        let grid1 = document.getElementById("grid1") as IgcGridComponent;
        grid1.data = data;
    }
    

    The id property is a string value and is the unique identifier of the grid which will be auto-generated if not provided, while data binds the grid, in this case to local data.

    The autoGenerate property tells the grid to auto generate the grid's IgcColumnComponent components based on the data source fields. It will also try to deduce the appropriate data type for the column if possible. Otherwise, the developer needs to explicitly define the columns and the mapping to the data source fields.

    Editable Web Components Grid

    Cada operação para edição de grade inclui operações em lote, o que significa que a API oferece a opção de agrupar edições em uma única chamada de servidor, ou você pode executar operações de edição/atualização de grade conforme elas ocorrem com interações de grade. Juntamente com uma ótima experiência de desenvolvedor como uma grade editável com operações CRUD, a grade inclui navegação por teclado semelhante ao Excel. A navegação em grade padrão comum está incluída, além da opção de substituir qualquer opção de navegação para atender às necessidades de seus clientes. Uma grade editável com um ótimo esquema de navegação é fundamental para qualquer aplicativo moderno de linha de negócios, com a grade Ignite UI facilitamos.

    Seguindo este tópico, você aprenderá mais sobre o modelo de célula e o modelo de edição e edição de célula.

    Grid Column Configuration

    IgcColumnComponent is used to define the grid's columns collection and to enable features per column like sorting and filtering. Cell, header, and footer templates are also available.

    Defining Columns

    Vamos desativar a autoGenerate propriedade e definir a coleção de colunas na marcação:

    <igc-grid id="grid1" auto-generate="false" allow-filtering="true">
        <igc-column field="Name" sortable="true" header=" "></igc-column>
        <igc-column field="AthleteNumber" sortable="true" header="Athlete number" filterable="false"></igc-column>
        <igc-column id="trackProgress" field="TrackProgress" header="Track progress" filterable="false"></igc-column>
    </igc-grid>
    
    constructor() {
        var grid1 = this.grid1 = document.getElementById('grid1') as IgcGridComponent;
        grid1.data = this.data;
    }
    

    Header Template

    O modelo de cabeçalho pode ser definido para modificar os cabeçalhos de coluna. Os snippets abaixo mostram como formatar o texto do cabeçalho em maiúsculas.

    <igc-column id="name" field="Name"></igc-column>
    
    constructor() {
        var name = this.name = document.getElementById('name') as IgcColumnComponent;
    
        this._bind = () => {
            name.headerTemplate = this.nameHeaderTemplate;
        }
    
        this._bind();
    }
    
    public nameHeaderTemplate = (ctx: IgcColumnTemplateContext) => {
        return html`
            ${this.formatUppercase(ctx.column.field)}
        `;
    }
    
    public formatUppercase(value: string) {
        return value.toUpperCase();
    }
    

    Observação: sempre que um modelo de cabeçalho é usado junto com a funcionalidade de agrupamento/movimentação, a área do cabeçalho da coluna se torna arrastável e você não pode acessar a parte de elementos personalizados do modelo de cabeçalho até marcá-los como não arrastáveis. Exemplo abaixo.

    <igc-column id="productName" field="ProductName" header="Product Name" groupable="true" has-summary="true"></igc-column>
    
    constructor() {
        var productName = this.productName = document.getElementById('productName') as IgcColumnComponent;
        productName.headerTemplate = this.productNameHeaderTemplate;
    }
    
    public productNameHeaderTemplate = (ctx: IgcColumnTemplateContext) => {
        return html`
            <div class="text">${ctx.column.field}</div>
            <igc-icon @click="${() => this.toggleSummary(ctx.column)}" name="functions" draggable="false"></igc-icon>
        `;
    }
    
    public toggleSummary(column: IgcColumnComponent) {
    }
    

    Como você pode ver, estamos adicionando Draggable o atributo definido como false.

    Cell Template

    Quando o modelo de célula é definido, ele altera todas as células da coluna. O objeto de contexto fornecido no modelo consiste no valor da célula fornecido implicitamente e no próprio objeto de célula. Ele pode ser usado para definir um modelo onde o texto das células pode ser formatado, por exemplo, como maiúsculas e minúsculas.

    <igc-column id="name" field="Name"></igc-column>
    
    constructor() {
        var name = this.name = document.getElementById('name') as IgcColumnComponent;
        name.bodyTemplate = this.nameCellTemplate;
    }
    
    public nameCellTemplate = (ctx: IgcCellTemplateContext) => {
        return html`
            ${this.formatTitleCase(ctx.implicit)}
        `;
    }
    
    public formatTitleCase(value: string) {
        return value.toUpperCase();
    }
    

    No trecho acima, fazemos uma referência ao valor da célula fornecido implicitamente. Isso é suficiente se você quiser apenas apresentar alguns dados e talvez aplicar algum estilo personalizado ou transformações de pipe sobre o valor da célula. No entanto, ainda mais útil é pegar a Cell própria instância, conforme mostrado abaixo:

    <igc-grid id="grid" auto-generate="false">
        <igc-column id="name" field="Name" data-type="string"></igc-column>
        <igc-column id="subscription" field="Subscription" data-type="boolean"></igc-column>
    </igc-grid>
    
    constructor() {
        var grid = this.grid = document.getElementById('grid') as IgcGridComponent;
        var name = this.name = document.getElementById('name') as IgcColumnComponent;
        var subscription = this.subscription = document.getElementById('subscription') as IgcColumnComponent;
        grid.data = this.data;
        name.bodyTemplate = this.nameCellTemplate;
        subscription.bodyTemplate = this.subscriptionCellTemplate;
    }
    
    public nameCellTemplate = (ctx: IgcCellTemplateContext) => {
        return html`
            <span tabindex="0" @keydown="${() => this.deleteRow(ctx.cell.id.rowIndex)}">${this.formatTitleCase(ctx.cell.value)}</span>
        `;
    }
    
    public subscriptionCellTemplate = (ctx: IgcCellTemplateContext) => {
        if (ctx.cell.value) {
                return html` <input type="checkbox" checked /> `;
        } else {
                return html` <input type="checkbox"/> `;
        }
    }
    
    public deleteRow(rowIndex: number) {
         this.grid.deleteRow(rowIndex);
    }
    
    public formatTitleCase(value: string) {
        return value.toUpperCase();
    }
    

    Observação: a grade expõe um tratamento padrão para os tipos de coluna numérica, de cadeia de caracteres, de data e booleana. Por exemplo, a coluna exibirá check um close ícone, em vez de verdadeiro/falso por padrão, para o tipo de coluna booleana.

    Quando implementado corretamente, o modelo de edição de célula também garante que a célula passe corretamente pelo ciclo de EditValue​ ​eventos de edição de grade.

    Cell Editing Template

    The column also accepts one last template that will be used when a cell is in edit mode. As with the other column templates, the provided context object is again the cell value and the cell object itself. Of course in order to make the edit-mode template accessible to end users, you need to set the editable property of the column to true.

    <igc-column id="price" field="Price" data-type="number" editable="true"></igc-column>
    
    constructor() {
        var price = this.price = document.getElementById('price') as IgcColumnComponent;
        price.inlineEditorTemplate = this.priceCellTemplate;
    }
    
    public priceCellTemplate = (ctx: IgcCellTemplateContext) => {
        return html`
            <label>
                Enter the new price tag
            </label>
            <input name="price" type="number" value="${ctx.cell.value}" @change="${() => this.updateValue(ctx.cell.value)}"  />
        `;
    }
    
    public updateValue(value: number) {
    }
    

    Certifique-se de verificar a API para Cell se acostumar com as propriedades fornecidas que você pode usar em seus modelos.

    Column Template API

    Each of the column templates can be changed programmatically at any point through the IgcColumnComponent object itself. For example in the code below, we have declared two templates for our user data. In our TypeScript code we'll get references to the templates themselves and then based on some condition we will render the appropriate template for the column in our application.

    <igc-grid>
        <!-- Column declarations -->
    </igc-grid>
    
    var user = this.user = document.getElementById('user') as IgcColumnComponent;
    // Return the appropriate template based on some condition.
    // For example saved user settings, viewport size, etc.
    user.bodyTemplate = this.smallView;
    
    public normalViewTemplate = (ctx: IgcCellTemplateContext) => {
        return html`
            <div class="user-details">${ ctx.cell.value }</div>
            <user-details-component></user-details-component>
        `;
    }
    
    public smallViewTemplate = (ctx: IgcCellTemplateContext) => {
        return html`
            <div class="user-details-small">${ ctx.cell.value }</div>
        `;
    }
    

    As propriedades da coluna também podem ser definidas no código no ColumnInit evento que é emitido quando as colunas são inicializadas na grade.

    public initColumns(column: IgcGridColumn) {
        if (column.field === 'ProductName') {
            column.sortable = true;
            column.editable = true;
        }
    }
    

    O código acima tornará a coluna ProductName classificável e editável e instanciará a interface do usuário dos recursos correspondentes (como entradas para edição etc.).

    Custom Display Format

    Há parâmetros opcionais para formatação:

    • format - determines what date/time parts are displayed, defaults to 'mediumDate', equivalent to 'MMM d, y'
    • timezone - the timezone offset for dates. By default uses the end-user's local system timezone
    • digitsInfo - decimal representation objects. Default to 1.0-3

    To allow customizing the display format by these parameters, the pipeArgs input is exposed. A column will respect only the corresponding properties for its data type, if pipeArgs is set. Example:

    <igc-column id="orderDate" field="OrderDate" data-type="date"></igc-column>
    
    private _columnPipeArgs: any | null = null;
        public get columnPipeArgs(): any {
            if (this._columnPipeArgs == null)
            {
                var columnPipeArgs: any = {};
                columnPipeArgs.format = "longDate";
                columnPipeArgs.timezone = "UTC";
                columnPipeArgs.digitsInfo = "1.2-2"
                this._columnPipeArgs = columnPipeArgs;
            }
            return this._columnPipeArgs;
        }
    
    constructor() {
        var orderDate = this.orderDate = document.getElementById('orderDate') as IgcColumnComponent;
        orderDate.pipeArgs = this.columnPipeArgs;
    }
    

    The OrderDate column will respect only the format and timezone properties, while the UnitPrice will only respect the digitsInfo.

    Todos os tipos de dados de coluna disponíveis podem ser encontrados no tópico oficial Tipos de coluna.

    Grid Data Structure

    The IgcGridComponent handles flat data and nested POJO (Plain old Java objects). The data structure specific for rendering is in the form:

    const OBJECT_ARRAY = [{
            ObjectKey1: value1,
            ObjectKey2: value2,
            // ...
            ObjectKeyN: valueN
        },
        // ...
      }];
    
    const POJO = [{
            ObjectKey1: value1,
            ObjectKey2: value2,
            // ...
            ObjectKeyN: {
              ObjectKeyN1: value1,
              ObjectKeyN2: value2,
              // ...
              ObjectKeyNM: valueNM,
            }
        },
        // ...
      }];
    

    WARNING: The key values must not contain arrays.

    If you use autoGenerate columns the data keys must be identical.

    Grid Data Binding

    Before going any further with the grid we want to change the grid to bind to remote data service, which is the common scenario in large-scale applications.

    You can do this by fetching the data from a given url receiving a JSON response and assigning it to the grid's data property that is used as the grid's data source:

    <igc-grid id="grid1"></igc-grid>
    
    public fetchData(url: string): void {
        fetch(url)
          .then(response => response.json())
          .then(data => this.onDataLoaded(data));
    }
    public onDataLoaded(jsonData: any[]) {
        var grid1 = document.getElementById("grid1") as IgcGridComponent;
        grid1.data = jsonData;
    }
    

    Observação: é melhor evitar a propriedade grid autoGenerate ao vincular a dados remotos por enquanto. Ele pressupõe que os dados estejam disponíveis para inspecioná-los e gerar as colunas apropriadas. Geralmente, esse não é o caso até que o serviço remoto responda e a grade gere um erro. A disponibilização autoGenerate, ao vincular ao serviço remoto, está em nosso roteiro para versões futuras.

    Complex Data Binding

    The IgcGridComponent supports binding to complex objects (including nesting deeper than one level) through a "path" of properties in the data record.

    Dê uma olhada no seguinte modelo de dados:

    interface AminoAcid {
        name: string;
        abbreviation: {
            short: string;
            long: string;
        }
        weight: {
            molecular: number;
            residue: number;
        },
        formula: {
            molecular: string;
            residue: string;
        }
    }
    

    Por exemplo, para exibir os pesos de um determinado aminoácido na grade, o seguinte trecho será suficiente

    <igc-column field="weight.molecular"></igc-column>
    <igc-column field="weight.residue"></igc-column>
    

    An alternative way to bind complex data, or to visualize composite data (from more than one column) in the IgcGridComponent is to use a custom body template for the column. Generally, one can:

    • use o value da célula, que contém os dados aninhados
    • use the cell object in the template, from which to access the ctx.cell.id.rowIndex or ctx.cell.id.rowID to get the row via the grid's API and retrieve any value from it and interpolate those in the template.
    <igc-column id="abbreviationLong" field="abbreviation.long"></igc-column>
    
    constructor() {
        var grid = (this.grid = document.getElementById("grid") as IgcGridComponent);
        var abbreviationLong = this.abbreviationLong = document.getElementById('abbreviationLong') as IgcColumnComponent;
        abbreviationLong.bodyTemplate = this.abbreviationLongCellTemplate;
    }
    
    public abbreviationLongCellTemplate = (ctx: IgcCellTemplateContext) => {
        return html`
            <div>
                <div>
                    ${ ctx.cell.value }
                        ${this.getName(ctx.cell.id.rowIndex)} 
                        ${this.getWeight(ctx.cell.id.rowIndex)}
                </div>
            </div>
        `;
    }
    
    public getName(rowIndex: number) {
        return this.grid.getRowByIndex(rowIndex).data["Name"];
    }
    public getWeight(rowIndex: number) {
        return this.grid.getRowByIndex(rowIndex).data["weight"]["molecular"];
    }
    

    Aqui está um exemplo de como o modelo de corpo é usado para exibir dados complexos. Abaixo estão os dados que vamos usar:

    export const EMPLOYEE_DATA = [
        {
            Age: 55,
            Employees: [
                {
                    Age: 43,
                    HireDate: new Date(2011, 6, 3),
                    ID: 3,
                    Name: "Michael Burke",
                    Title: "Senior Software Developer"
                },
                {
                    Age: 29,
                    HireDate: new Date(2009, 6, 19),
                    ID: 2,
                    Name: "Thomas Anderson",
                    Title: "Senior Software Developer"
                },
                {
                    Age: 31,
                    HireDate: new Date(2014, 8, 18),
                    ID: 11,
                    Name: "Monica Reyes",
                    Title: "Software Development Team Lead"
                },
                {
                    Age: 35,
                    HireDate: new Date(2015, 9, 17),
                    ID: 6,
                    Name: "Roland Mendel",
                    Title: "Senior Software Developer"
                }],
            HireDate: new Date(2008, 3, 20),
            ID: 1,
            Name: "John Winchester",
            Title: "Development Manager"
        }
    ]
    

    O modelo personalizado para a coluna, que renderizará os dados aninhados:

    <igc-column id="employees" field="Employees" header="Employees" width="40%"></igc-column>
    
    constructor() {
        var employees = this.employees = document.getElementById('employees') as IgcColumnComponent;
        employees.bodyTemplate = this.addressCellTemplate;
    }
    
    public addressCellTemplate = (ctx: IgcCellTemplateContext) => {
        return html`
        <igc-expansion-panel>
                <div slot="title" style="font-size: 1.1em; font-weight: bold; margin-top: 1rem; margin-bottom: 0.25rem;">
                ${ctx.cell.value[0].Name}
                </div>
                <div class="description">
                    <div style="display: flex; align-items: center;">
                        <div for="title" style="width: 2rem; margin: 0rem;">Title</div>
                        <input id='Title' type="text" name="title" value="${ctx.cell.value[0].Title}" style="text-overflow: ellipsis;" />
                    </div>
                    <div style="display: flex; align-items: center;">
                        <div for="age" style="width: 2rem; margin: 0rem;">Age</div>
                        <input id='Age' type="text" name="title" value="${ctx.cell.value[0].Age}" style="text-overflow: ellipsis;" />
                    </div>
                </div>
            </igc-expansion-panel>
        `;
    }
    

    E o resultado dessa configuração é:

    Working with Flat Data Overview

    The flat data binding approach is similar to the one that we already described above, but instead of cell value we are going to use the data property of the IgcGridRow.

    Since the Web Components grid is a component for rendering, manipulating and preserving data records, having access to every data record gives you the opportunity to customize the approach of handling it. The data property provides you this opportunity.

    Abaixo estão os dados que vamos usar:

    export const DATA: any[] = [
        {
            Address: "Obere Str. 57",
            City: "Berlin",
            CompanyName: "Alfreds Futterkiste",
            ContactName: "Maria Anders",
            ContactTitle: "Sales Representative",
            Country: "Germany",
            Fax: "030-0076545",
            ID: "ALFKI",
            Phone: "030-0074321",
            PostalCode: "12209",
            Region: null
        }
    ]
    

    O modelo personalizado:

    <igc-column id="address" field="Address" header="Address" width="25%" editable="true"></igc-column>
    
    constructor() {
        var address = this.address = document.getElementById('address') as IgcColumnComponent;
        address.bodyTemplate = this.addressCellTemplate;
    }
    
    public addressCellTemplate = (ctx: IgcCellTemplateContext) => {
        return html`
            <div class="address-container">
            <!-- In the Address column combine the Country, City and PostCode values of the corresponding data record -->
                <span><strong>Country:</strong> ${this.getCountry(ctx.cell.id.rowIndex)}</span>
                <br/>
                <span><strong>City:</strong> ${this.getCity(ctx.cell.id.rowIndex)}</span>
                <br/>
                <span><strong>Postal Code:</strong> ${this.getPostalCode(ctx.cell.id.rowIndex)}</span>
            </div>
        `;
    }
    
    public getCountry(rowIndex: number) {
        return this.grid.getRowByIndex(rowIndex).data["Country"];
    }
    
    public getCity(rowIndex: number) {
         return this.grid.getRowByIndex(rowIndex).data["City"];
    }
    
    public getPostalCode(rowIndex: number) {
         return this.grid.getRowByIndex(rowIndex).data["PostalCode"];
    }
    

    Lembre-se de que, com o modelo definido acima, você não poderá fazer operações de edição, portanto, precisamos de um modelo de editor.

    <igc-column id="address" field="Address" data-type="number" width="25%" editable="true"></igc-column>
    
    constructor() {
        var address = this.address = document.getElementById('address') as IgcColumnComponent;
        address.inlineEditorTemplate = this.webGridCompositeAddressEditCellTemplate;
    }
    
    public webGridCompositeAddressEditCellTemplate = (ctx: IgcCellTemplateContext) => {
        var cell = ctx.cell as any;
        if (cell === undefined || cell.row === undefined || cell.row.data === undefined) {
            return html``
        }
    
        function keyUpHandler(event: any, ctx: IgcCellTemplateContext) {
            var cell = ctx.cell as any;
            if (cell !== undefined && cell.row !== undefined && cell.row.data !== undefined) {
                cell.row.data[event.target.id] = event.target.value;
            }
            }
    
        return html`<div class="address-container--edit" style="display: inline-grid">
                <div>
                    <span><strong>Country:</strong></span>
                    <input id='Country' @keyup=${(e: any) => keyUpHandler(e, ctx)} value="${cell.row.data.Country}"></input>
                    <br>
                    <span><strong>City:</strong></span>
                    <input id='City' @keyup=${(e: any) => keyUpHandler(e, ctx)} value="${cell.row.data.City}"></input>
                </div>
                <div>
                    <span><strong>Postal Code:</strong></span>
                    <input id='PostalCode' @keyup=${(e: any) => keyUpHandler(e, ctx)} value="${cell.row.data.PostalCode}"></input>
                    <br>
                    <span><strong>Selected:</strong></span>
                    <input id='Phone' @keyup=${(e: any) => keyUpHandler(e, ctx)} value="${cell.row.data.Phone}"></input>
                </div>
                <br>
            </div>`;
    }
    

    Working with Flat Data Example

    Using code snippets from previous section will result in the following example of IgcGridComponent

    Keyboard Navigation

    Keyboard navigation of the IgcGridComponent provides a rich variety of keyboard interactions for the user. It enhances accessibility and allows intuitive navigation through any type of elements inside (cell, row, column header, toolbar, footer, etc.).

    Styling Web Components Grid

    Nota: A grade usa o layout de grade css, que não é suportado no IE sem prefixação, conseqüentemente não será renderizado corretamente.

    In addition to the predefined themes, the grid could be further customized by setting some of the available CSS properties. In case you would like to change the header background and text color, you need to set a class for the grid first:

    <igc-grid class="grid"></igc-grid>
    

    Em seguida, defina as--header-background propriedades e--header-text-color CSS para essa classe:

    .grid {
        --header-background: #494949;
        --header-text-color: #FFF;
    }
    

    Known Limitations

    Limitação Descrição
    As larguras das colunas definidas empercentage epx Atualmente, não oferecemos suporte à mistura de larguras de coluna com% epx.
    Ao tentar filtrar uma coluna do tiponumber Se um valor diferente do inseridonumber na entradaNaN de filtragem for retornado devido a uma conversão incorreta.
    A gradewidth não depende das larguras das colunas Owidth de todas as colunas não determina a abrangência da grade em si. Ele é determinado pelas dimensões do contêiner pai ou pela grade definida.width
    Grade aninhada no contêiner pai Quando awidth grade não está definida e é colocada em um contêiner pai com dimensões definidas, a grade se estende até esse contêiner.
    Estratégia de Detecção de Mudança de GradeOnPush A grade opera comChangeDetectionStrategy.OnPush isso, sempre que alguma personalização aparecer, certifique-se de que a grade seja notificada sobre as alterações que acontecem.
    As colunas têm uma largura mínima permitida. Dependendo da--ig-size variável CSS, eles são os seguintes:
    "pequeno": 56px
    "médio": 64px
    "grande": 80px
    Se a largura for menor que o mínimo permitido for definida, isso não afetará os elementos renderizados. Eles serão renderizados com a largura mínima permitida para o correspondente--ig-size. Isso pode levar a um comportamento inesperado com a virtualização horizontal e, portanto, não é suportado.
    A altura da linha não é afetada pela altura das células que não estão renderizadas no momento. Devido à virtualização, uma coluna com um modelo personalizado (que altera a altura da célula) que não está no modo de exibição não afetará a altura da linha. A altura da linha será afetada somente enquanto a coluna relacionada for rolada na exibição.

    API References

    Additional Resources

    Nossa comunidade é ativa e sempre acolhedora para novas ideias.