Salesforce/LWC datatableへナビゲーション項目を表示する

lwcコンポーネント内で、datatableにナビゲーション項目を配置したいことはよくあると思います。ナビゲーションURLを生成するために、NavigationMixinが標準で用意されていますので、それを使います。

//customSearch.js
import { LightningElement, track } from 'lwc';
import { NavigationMixin } from "lightning/navigation";
import search from "@salesforce/apex/CustomAccountSearch.search";

export default class CustomSearch extends NavigationMixin(LightningElement) {
  columns = [
    {
      label: "取引先",
      fieldName: "url",
      type: "url",
      typeAttributes: { label: { fieldName: 'Name' } }
    },
    {
      label: "業種",
      fieldName: "Industry",
    }
  ];
  @track accounts;

  async onSearch() {
    const found = await search();
    const converted = await Promise.all(found.map(async (a) => {
      const url = await this.makeUrl(a);
      return {
        ...a,
        url
      };
    }));
    this.accounts = converted.slice(0, 100);
  }
  async makeUrl(account) {
    return this[NavigationMixin.GenerateUrl]({
      type: "standard__recordPage",
      attributes: {
        objectApiName: 'Account',
        recordId: account.Id,
        actionName: "view"
      }
    });
  }
}
/* customSearch.html */
<template>
  <lightning-button onclick={onSearch} label="search"></lightning-button>
  <div class="slds-scrollable" style="height:10rem">
    <lightning-datatable
      key-field="Id"
      columns={columns}
      data={accounts}
    ></lightning-datatable>
  </div>
</template>
//CustomAccountSearch.cls
public with sharing class CustomAccountSearch {
  @AuraEnabled(cacheable=false)
  public static List<Account> search() {
    return [
      SELECT Id, Name, Industry
      FROM Account
      ORDER BY Name Asc
    ];
  }
}

これで目的は達成できますが、GenerateUrlをonSearchで待ってしまっています。

chromeのPerformanceタブ

GenerateUrlは非同期でURLを生成させようとしていますので、従いましょう。

type=”navigate”な列を受け付けるように、datatableを拡張します。今回はオブジェクトページへのナビゲーション項目を作成したいので、レコードのIdをvalueとして、別途必要なラベルとオブジェクト名はlabelとobjectとして渡せるようにします。

//customDatatable.js
import LightningDatatable from "lightning/datatable";
import navigateCell from "./navigateCell.html";

export default class CustomDatatable extends LightningDatatable {
  static customTypes = {
    navigate: {
      template: navigateCell,
      typeAttributes: ["label", "object"]
    }
  };
}
/* navigateCell.html */
<template>
  <c-custom-datatable-navigate-cell
    value={value}
    label={typeAttributes.label}
    object={typeAttributes.object}
  ></c-custom-datatable-navigate-cell>
</template>

navigateを実装します。GenerateUrlによるURLの生成は、ここまで遅延されます。Id、ラベル、オブジェクト名が渡ってきているので、それを元にURLを生成し、lightning-formatted-urlを使用してリンクを作ります。

//customDatatableNavigateCell.js
import { LightningElement, api, track } from "lwc";
import { NavigationMixin } from "lightning/navigation";

export default class CustomDatatableNavigateCell extends NavigationMixin(LightningElement) {
  @api value;
  @api label;
  @api object;

  @track url;

  async connectedCallback(){
    this.url = await this.generateRecordPageUrl(this.object, this.value);
  }
  generateRecordPageUrl(objectApiName, recordId) {
    return this[NavigationMixin.GenerateUrl]({
      type: "standard__recordPage",
      attributes: {
        objectApiName: objectApiName,
        recordId: recordId,
        actionName: "view"
      }
    });
  }
}
/* customDatatableNavigateCell.html */
<template>
  <lightning-formatted-url
    value={url}
    label={label}
  ></lightning-formatted-url>
</template>

type=”navigate”な列を受け付けるc-custom-datatableができました。

//customSearchAsync.js
import { LightningElement, track } from 'lwc';
import search from "@salesforce/apex/CustomAccountSearch.search";

export default class CustomSearchAsync extends LightningElement {
  columns = [
    {
      label: "取引先",
      fieldName: "Id",
      type: "navigate",
      typeAttributes: { label: { fieldName: "Name" }, object: 'Account' }
    },
    {
      label: "業種",
      fieldName: "Industry",
    },
  ];
  @track accounts;

  async onSearch() {
    const found = await search();
    this.accounts = found.slice(0, 100);
  }
}
/* customSearchAsync.html */
<template>
  <lightning-button onclick={onSearch} label="search (customSearchAsync)"></lightning-button>
  <div class="slds-scrollable" style="height:10rem">
    <c-custom-datatable
      key-field="Id"
      columns={columns}
      data={accounts}
    ></c-custom-datatable>
  </div>
</template>

見た目変わらず、生成を遅延させることができました。さらに、生成ロジックをセルにお任せすることができたので、トップレベルでその実装をする必要がなくなりました。

onSearchの処理の長さが解決できました。

chromeのPerformanceタブ

コメントを残す

%d