Display Data Using Base Components

A common way to display data is to use datatables. LWC provides the lightning-datatable base component for displaying large amounts of data. lightning-datatable supports a wide range of column types that are ideal for displaying record data, such as currency, date, email, and even a dropdown menu for row-level actions. You can also load more data by implementing pagination or infinite scrolling on the datatable.

To display your records using lightning-datatable, set key-field="Id" and specify the data and column properties.

<!-- prettier-ignore -->
<!-- datatableWithGraphql.html -->
<template>
  <template lwc:if={accounts}>
    <lightning-datatable key-field="Id" data={accounts} columns={columns} hide-checkbox-column>
    </lightning-datatable>
  </template>
  <template lwc:elseif={errors}>
    <!-- Display errors -->
  </template>
</template>

In your JavaScript, create your columns and define your data using key-value pairs when it’s returned by the GraphQL wire adapter.

// datatableWithGraphql.js
import { LightningElement, wire } from "lwc";
import { gql, graphql } from "lightning/graphql";

const columns = [
  { label: "Name", fieldName: "Name" },
  { label: "Phone", fieldName: "Phone", type: "phone" },
  { label: "Website", fieldName: "Website", type: "url" },
  { label: "Annual Revenue", fieldName: "AnnualRevenue", type: "currency" },
];

export default class DatatableWithGraphql extends LightningElement {
  // Array of accounts to display
  accounts = undefined;
  // Errors from the wire adapter
  errors = undefined;
  // Columns for datatable
  columns = columns;

  @wire(graphql, {
    query: gql`
      query AccountWithName {
        uiapi {
          query {
            Account {
              edges {
                node {
                  Id
                  Name {
                    value
                  }
                  Phone {
                    value
                  }
                  Website {
                    value
                  }
                  AnnualRevenue {
                    displayValue
                  }
                }
              }
            }
          }
        }
      }
    `,
  })
  gqlQuery({ data, errors }) {
    if (data) {
      this.accounts = data.uiapi.query.Account.edges.map((edge) => ({
        Id: edge.node.Id,
        Name: edge.node.Name.value,
        Phone: edge.node.Phone.value,
        Website: edge.node.Website.value,
        AnnualRevenue: edge.node.AnnualRevenue.displayValue,
      }));
    }
    this.errors = errors;
  }
}

Add pagination to the datatable with a refresh button and a next button. The refresh button takes users back to the start of the results. The next button becomes disabled when the end of the results is reached.

note: Backward pagination using last and before isn’t currently supported.

<!-- datatableWithGraphqlPagination -->
<template>
  <lightning-button-icon icon-name="utility:skip_back" onclick="{resetPagingCursor}"
    ><label>Reset Pagination</label></lightning-button-icon
  >
  <lightning-button-icon
    disabled="{isFinalPage}"
    class="next"
    icon-name="utility:chevronright"
    onclick="{getNextPage}"
    ><label>Next</label></lightning-button-icon
  >
  <p>Total records found: {totalCount}</p>
  <p>Page {currentPage} of {totalPages}</p>

  <template lwc:if="{accounts}">
    <lightning-datatable key-field="Id" data="{accounts}" columns="{columns}" hide-checkbox-column>
    </lightning-datatable>
  </template>
  <template lwc:elseif="{errors}">
    <!-- Display errors -->
  </template>
</template>

Building on the previous lightning-datatable example, query the pageInfo object for cursor and pagination information.

// datatableWithGraphqlPagination.js
import { LightningElement, wire } from "lwc";
import { gql, graphql } from "lightning/graphql";

const columns = [
  { label: "Name", fieldName: "Name" },
  { label: "Phone", fieldName: "Phone", type: "phone" },
  { label: "Website", fieldName: "Website", type: "url" },
  { label: "Annual Revenue", fieldName: "AnnualRevenue", type: "currency" },
];

export default class DatatableWithGraphqlPagination extends LightningElement {
  // Array of accounts to display
  accounts = undefined;
  // Errors from the wire adapter
  errors = undefined;
  // Columns for datatable
  columns = columns;

  // Cursor of the last returned record
  lastCursor = null;

  // Cursor for the next page
  endCursor = null;

  // Checks if the page is the last page
  // Disables the next page button if true
  isFinalPage = false;

  // Total number of query results
  totalCount = null;
  page = 1;
  totalPages = 1;
  @wire(graphql, {
    query: "$accountQuery",
    variables: "$variables",
  })
  gqlQuery({ data, errors }) {
    if (data) {
      this.accounts = data.uiapi.query.Account.edges.map((edge) => ({
        Id: edge.node.Id,
        Name: edge.node.Name.value,
        Phone: edge.node.Phone.value,
        Website: edge.node.Website.value,
        AnnualRevenue: edge.node.AnnualRevenue.displayValue,
      }));
      this.isFinalPage = !data.uiapi.query.Account.pageInfo.hasNextPage;
      this.endCursor = data.uiapi.query.Account.pageInfo.endCursor;
      this.totalCount = data.uiapi.query.Account.totalCount;
      this.totalPages = Math.ceil(this.totalCount / 10);
    }
    this.errors = errors;
  }

  // Define the GraphQL query
  get accountQuery() {
    return gql`
      query AccountWithName($after: String) {
        uiapi {
          query {
            Account(after: $after) {
              edges {
                node {
                  Id
                  Name {
                    value
                  }
                  Phone {
                    value
                  }
                  Website {
                    value
                  }
                  AnnualRevenue {
                    displayValue
                  }
                }
              }
              pageInfo {
                endCursor
                hasNextPage
                hasPreviousPage
              }
              totalCount
            }
          }
        }
      }
    `;
  }

  // Define variables for the GraphQL query
  get variables() {
    return {
      after: this.lastCursor,
    };
  }

  get currentPage() {
    return this.totalCount === 0 ? 0 : this.page;
  }

  // Click handler for the reset button
  resetPagingCursor(event) {
    this.lastCursor = null;
    this.page = 1;
  }

  // Click handler for the next page button
  getNextPage(event) {
    if (!this.isFinalPage) {
      this.lastCursor = this.endCursor;
      this.page++;
    }
  }
}