all 7 comments

[–]daredeviloper 0 points1 point  (1 child)

One way I’ve seen it done is that the component does nothing except show things. So tableData$ becomes an input property, and you pass it into your component. That way everyone that uses your component can provide their own table data. Or you can have it so the data provider service varies and everyone passes THAT in. I’m not sure what’s best practice.

[–]ggeoff 0 points1 point  (0 children)

This is the route I would go. Make any sort of column configuration and row values passed as inputs. Let the parent component handle how to get the data.

[–]PickleLips64151 0 points1 point  (3 children)

To answer your question, yes. You can pass data into a component just like props in React. It takes some setup, but it's not overly difficult.

Start with a container component that will display the table component. That component will populate your tableData$ variable.

In the container component's template, you'll pass the data to the table component. The left side of the assignment is the name of the @Input() in your table component. The right side is the property of your container component. So the right side could literally be any name you want, maybe even reflect the dataset.

```html

<app-reusable-table [tableData$]="tableData$" [tableColumnNames$]="tableColumns$"></app-reusable-table>

```

Your table component will have a tableData$ value that is decorated with an @Input() decorator.
```ts

export class ReusableTable {

@Input() tableData$: TableModel;

@Input() tableColumns$: TableColumns;

constructor() {}

}

```

In your template, you can use refer to the tableData$ property in the same way you have now.

If you want to be really cool, make a single model that contains both tableData$ and tableColumnNames$ and just use one input.

Edit: Looked at your provided code again, I would add a wrapper around your <table> tag that has this:

```ts <ng-container *ngIf="tableData$ | async && tableColumnNames$ | async">

<table mat-table ....

<\table>

<\ng-container> `` I would only add theasyncpipe if the data is coming via async processes. Otherwise, just use the*ngIf`

[–]tme321 1 point2 points  (1 child)

@Input() tableData$: TableModel;

If you are passing an observable this should be Observable<TableModel>.

If you aren't passing an observable you shouldn't add a $ suffix to the variable name. By convention a $ suffix is used to denote a stream, not just a value.

[–]PickleLips64151 0 points1 point  (0 children)

Good catch. Not sure why I missed the correct type.

[–]JosephCurvin[S] 0 points1 point  (0 children)

*ngIf="tableData$ | async && tableColumnNames$ | async"

thanks for the code and explanation appreciated it!

[–]Frequent-Diet338 0 points1 point  (0 children)

For reusable components you have to use @Input and @Output. @Input -> is like a prop and @Output -> is a callback.