Использование пользовательского шаблона с TableItem в Carbon Design (Angular) не дает ожидаемой функциональности

#angular

#angular

Вопрос:

Согласно документации IBM Carbon Design System, можно определить ng-template и ссылаться на него с помощью @ViewChild и protected переменной.

Затем, при определении new TableItem , следует ссылаться на эту переменную и присоединять данные, связанные с шаблоном, через атрибут let-data , в итоге:

 import {
  TableItem,
  TableHeaderItem
} from 'carbon-components-angular';

/* ... */

export class HomeComponent implements OnInit {

  @ViewChild('customItemTemplate')
  protected customItemTemplate: TemplateRef<any>;

  /* ... */

initialiseTable(records: any) {
    this.model = new TableModel();
    this.model.header = [
      new TableHeaderItem({ data: 'Column name' }),
      /* ... */
    ];


    tableRow = [
      new TableItem({ data: { name: 'Full details', link: '/record/' }, template: this.customItemTemplate }),
      /* ... */
    ];

    this.model.data = [tableRow];

}
  

И в HTML моего компонента у меня есть следующее ng-template :

 <ng-template #customItemTemplate let-data="data">
  <a [routerLink]="data.link">{{data.name}}</a>
</ng-template>
  

Я пробовал переключаться между разными версиями: 9.0.0 и 10.0.0.rc.0.

Когда я посмотрел на представление, где должен быть пользовательский шаблон, я вижу [object Object] .

Кто-нибудь может помочь мне исправить это, чтобы мой шаблон вставлялся правильно, и я мог предоставить ссылку на другое представление?

Обновление: я зарегистрировал это как проблему на GitHub и получил действительно быстрый ответ. Меня попросили предложить сокращенную демонстрационную версию, которую вы можете найти через Codesandbox здесь. Связанная проблема с GitHub здесь

Ответ №1:

Я нашел проблему!

Хотите верьте, хотите нет, но это связано с кодом, предоставленным документацией IBM по разбиению на страницы.

Рассматриваемый код, который по умолчанию вызывает проблемы с пользовательскими шаблонами, используется для функциональности разбивки на страницы в демонстрации:

   protected prepareData(data: Array<Array<any>>) {
      // create new data from the service data
      let newData = [];
      data.forEach(dataRow => {
          let row = [];
          dataRow.forEach(dataElement => {
              row.push(new TableItem({
                  data: dataElement,
                  template: typeof dataElement === "string" ? undefined : this.paginationTableItemTemplate
                  // your template can handle all the data types so you don't have to conditionally set it
                  // you can also set different templates for different columns based on index
              }));
          });
          newData.push(row);
      });
      return newData;
  }
  

Для справки, вот соответствующая документация. Если вы прокрутите вниз до заголовка «Использовать разбивку на страницы в качестве нижнего колонтитула таблицы», вы увидите код, о котором я говорю 🙂

Решение

Функция должна проверять тип, проходящий при prepareData вызове во время разбивки на страницы:

 protected prepareData(data: Array<Array<any>>) {
    // create new data from the service data
    const newData: Array<Array<TableItem>> = [];
    data.forEach(dataRow => {
      const row: Array<TableItem> = [];
      dataRow.forEach(dataElement => {
        let template;
        if (dataElement.template) {
          template = dataElement.template;
        } else if (typeof dataElement === 'string') {
          template = undefined;
        } else {
          template = this.paginationTableItemTemplate;
        }

        row.push(
          new TableItem({
            data: dataElement.data,
            template: template
          })
        );
      });
      newData.push(row);
    });
    return newData;
  }
  

И теперь это работает как по маслу.

Я обновил команду через GH и посмотрю о PR для документов по этому поводу — не будет редкостью, что люди копируют код и забывают об этом, как это сделал я. Пользовательские шаблоны начали работать только тогда, когда я вернул всю функциональность, затем я перешел к базовым принципам.