Отображение Related List-а в виде таблицы с использованием lightning-datatable и uiRelatedListApi

Добрый день!

Ранее для отображения связанного списка (Related List) с помощью компонента lightning-datatable при создании кастомных LWC страниц/компонент, необходимо было воспользоваться Apex методом для получения самого связанного списка (все возможные варианты реализации очень подробно расписаны на просторах интернета). Однако в Spring’22 и Summer’22 разработчики SF предоставили нам новое API - lightning/uiRelatedListApi для работы со связанными списками без необходимости использования Apex-а.

В одном из последних проектов, мне как раз необходимо было реализовать кастомный LWC компонент который кроме всего прочего должен был отображать в виде таблицы (требование заказчика) один из связанных списков родительского компонента. Для получения данных связанного списка я решил отойти от предыдущей практики использования Apex-а и воспользоваться преимуществами нового API lightning/uiRelatedListApi применив getRelatedListRecords wire adapter.

Однако решение в лоб оказалось не рабочим, каково было моё удивление :slight_smile:, когда добросовестно скопированный и немного изменённый под мою задачу пример из документации вместо таблицы показал мне всем известную фигуру из среднего пальца.

Пришлось читать документацию более внимательно, ведь как известно, вдумчиво читать инструкцию начинаешь либо когда что-то не работает либо когда всё уже сломалось!

Проанализировав с помощью

console.log(JSON.stringify(data))

очень полезная штука, на мой взгляд, структуру данных входных параметров и возвращаемых результатов APEX метода (старый вариант) и getRelatedListRecords (новый вариант), на удивление они оказались разными :smile: !

Не найдя описания в интернете и имея твердое решение использовать именно новый подход получения данных и отображения с помощью компонента lightning-datatable я решил попробовать преобразовать структуру данных получаемых методом getRelatedListRecords в структуру данных подходящую для отображения компонентом lightning-datatable.

И так реализация:

Упрощенный пример создан в стандартном DevOrg-е, на странице Account-а, мы будем отображать связанный с Account-ом список его Case-ов.

caseRelatedList.html

<template>
	<lightning-datatable
		key-field	=	"Id"
		data		=	{cases}
		columns		=	{casesColumns}
		show-row-number-column
		hide-checkbox-column>
	</lightning-datatable>
</template>

caseRelatedList.js

import { LightningElement, api, wire}	from 'lwc';
import { getRelatedListRecords }		from 'lightning/uiRelatedListApi';

import CASE_ID_FIELD					from '@salesforce/schema/Case.Id';
import CASE_CASE_NUMBER_FIELD			from '@salesforce/schema/Case.CaseNumber';
import CASE_STATUS_FIELD				from '@salesforce/schema/Case.Status';

const CASE_FIELDS	=	[
							CASE_ID_FIELD,		
							CASE_CASE_NUMBER_FIELD,		
							CASE_STATUS_FIELD
						];

const CASE_COLUMNS	=	[
							{ 
								label		:	'Case Number',	
								fieldName	:	CASE_CASE_NUMBER_FIELD.fieldApiName
							},
							{ 
								label		:	'Status',	
								fieldName	:	CASE_STATUS_FIELD.fieldApiName
							}
						];

export default class CaseRelatedList extends LightningElement {

	@api recordId;

	cases;
	casesColumns = CASE_COLUMNS;

	@wire(
		getRelatedListRecords, 
		{
        	parentRecordId	:	"$recordId",
        	relatedListId	:	'Cases',
        	fields			:	CASE_FIELDS.map(field => `${field.objectApiName}.${field.fieldApiName}`)
    	}
	)
	listCases({ error, data }) {
		if (data) {
			this.cases = data.records.map(
				record	=>	Object.fromEntries(
								new Map(
									Object.keys(record.fields).map(
										field	=>	[field, record.fields[field].value]
									)
								)
							)
			);
		} else if (error) {
			console.log(error);
		}
    }
 }

Основных моментов два:

  1. Подготовка списка полей как входного параметра для метода getRelatedListRecords:
fields : CASE_FIELDS.map(field => `${field.objectApiName}.${field.fieldApiName}`)

В документации метод getRelatedListRecords требует список необходимых полей передавать в следующем виде:

fields: ['Contact.Name','Contact.Id']

что собственно и реализует метод map применяемый для массива полей CASE_FIELDS.

  1. Преобразование структуры полученных данных в структуру с которой работает компонент lightning-datatable:
this.cases = data.records.map(
	record	=>	Object.fromEntries(
					new Map(
						Object.keys(record.fields).map(
							field	=>	[field, record.fields[field].value]
						)
					)
				)
);

Это всё!

Преимущества и недостатки, субъективное мнение:

К преимуществам я бы отнёс, то что для отображения используется стандартный компонент lightning-datatable со своей закулисной магией, мне нужно только структуру подготовить, а остальное он сам всё за меня сделает и отсутствие APEX метода - меньше зависимого кода.

К недостаткам относиться, то что, вряд ли такой подход применим для таблиц которые нужно будет редактировать (inline), хотя честно говоря я не проверял.

Спасибо за внимание!

8 Likes