Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Documentation: Using a custom template with a TableItem in Carbon Design (Angular) not yielding expected functionality #455

Closed
Quasso opened this issue Mar 28, 2019 · 10 comments
Labels
component: Table For Table issues documentation Something that needs documented

Comments

@Quasso
Copy link

Quasso commented Mar 28, 2019

Detailed description

According to the IBM Carbon Design System docs, one can define an ng-template and reference it using @ViewChild and a protected variable.

Then, when defining a new TableItem, one should reference this variable and attach data associated with the template via the attribute let-data, in summary:

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];

}

And in my component's HTML I have the following ng-template:

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

I've tried switching between different versions: 9.0.0 and 10.0.0.rc.0.

When I looked at the view, where the custom template ought to be, I see [object Object].

Additional information

Related StackOverflow question

@cal-smith
Copy link
Contributor

That definitely shouldn't be happening 🤔

Could you create a minimal codesandbox reproduction to help us debug this? https://codesandbox.io/s/0129r494ql

Also, what version of carbon-components-angular are you seeing this with?

@Quasso
Copy link
Author

Quasso commented Mar 28, 2019

Sure thing thanks, working on that now! As for version, as mentioned in OP: "I've tried switching between different versions: 9.0.0 and 10.0.0.rc.0."

Same problem occurs with either version.

Will post my fork here shortly--thanks for the prompt response I really need this feature!

@Quasso
Copy link
Author

Quasso commented Mar 28, 2019

Here you go @cal-smith, please find by Codesandbox here--pagination is not fully working but irrelevant because I have intentionally missed out some extra code

@cal-smith
Copy link
Contributor

Thanks!

My apologies, 9.0.0 and 10.0.0.rc.0 would refer to the carbon-components version - this is separate from the carbon-components-angular version (latest there being 2.40.3)

Either way I see the issue now ... You'll need to move this.initialiseTable(); from the constructor into ngOnInit ... generally component init things should be contained in ngOnInit - TemplateRefs aren't guaranteed to be instantiated when the constructor runs

here's a working codesandbox: https://codesandbox.io/embed/qvj345k7wj

@Quasso
Copy link
Author

Quasso commented Mar 28, 2019

Ah I see my apologies! I was on 2.3x.y (can't remember exactly) then upgraded to latest. As it happens, in my actual controller I do have it from an OnInit--just an oversight in the simplified example. So it appears something else is afoot--think I may have spotted what it is. I'll report back with more details if what I noticed solves it :)

@Quasso
Copy link
Author

Quasso commented Mar 28, 2019

@cal-smith I've discovered what the problem was. It was a little un-obvious, but it does actually have to do with some code I lifted from the Carbon Design docs funnily enough!

The code in question which is causing issues by default with custom templates is this, used for the pagination functionality in the demo:

  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;
  }

The issue is that data that has been prepared already that is passed to this formatter function loses the TemplateRef it is supposed to inject.

A simple solution I made was to check for the property template on dataElement, like so:

  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 => {
        if (dataElement.template) {
          row.push(
            new TableItem({
              data: dataElement.data,
              template: dataElement.template,
            })
          );
        } else {
          row.push(
            new TableItem({
              data: dataElement.data,
              template: typeof dataElement === 'string' ? undefined : this.paginationTableItemTemplate
            })
          );
        }

      });
      newData.push(row);
    });
    return newData;
  }

And now it works like a charm. I'm sure the positioning of the TableItem is irrelevant too. I could do a neater solution but that's the easiest way for now which works. Should I update the codesandbox to show the issue at play and the fix?

For reference, here is the relevant documentation. If you scroll down to the header "Use pagination as table footer" you'll see the code I'm talking about :)

@Quasso
Copy link
Author

Quasso commented Mar 28, 2019

Update, this is the code I'm now using in order to prepareData for pagination:

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;
  }

@cal-smith
Copy link
Contributor

Ah! That makes total sense ... if you want, a PR to improve the documentation for that section would definitely be appreciated 👍

@cal-smith cal-smith added documentation Something that needs documented component: Table For Table issues labels Mar 29, 2019
@cal-smith cal-smith changed the title Using a custom template with a TableItem in Carbon Design (Angular) not yielding expected functionality Documentation: Using a custom template with a TableItem in Carbon Design (Angular) not yielding expected functionality May 16, 2019
@Quasso
Copy link
Author

Quasso commented May 23, 2019

Hey @cal-smith sorry had a really busy period lately as been closing off a funding round. I'll get this done soon if it still needs doing?! Thanks :)

@zvonimirfras
Copy link
Member

@Quasso Hi Alex, based on what I've seen, documentation is accurate and snippet is from a working demo. It did not work for you by simply copy pasting because you're organizing your code and data differently than the sample.

That's fine and it's ok to organize your code and data how you see fit, that's why we provide a way to customize table and loading.

Providing that I'm not missing something, I'm not sure where you got lost while reading the docs and how can we prevent that from happening in future to someone else.

Feel free to open a PR with that and let's make our docs better :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
component: Table For Table issues documentation Something that needs documented
Projects
None yet
Development

No branches or pull requests

3 participants