2

I want to build a custom table with mat-table where for the last column and for every row I want to define a custom component. This works. But the custom components are for some input, so the user can select some options or type something in.

<mat-table class="mat-elevation-z8" #table [dataSource]='dataSource'>

<ng-container matColumnDef='value'>
      <mat-header-cell *matHeaderCellDef>Values</mat-header-cell>
      <mat-cell *matCellDef='let row'>
          <app-dropdown-element #drop *ngIf="row.value == 'dropdown'" [options$]='row.$options'></app-dropdown-element>  

          <app-input-element #text *ngIf="row.value == 'text'" [title]=''></app-input-element>

          <app-input-number-element #num *ngIf="row.value == 'number'" [number$]='row.$number'></app-input-number-element>

      </mat-cell>
    </ng-container>
</mat-table>

That is what I get when I load the component outside the table

'selected' value is also correct:
DropdownElementComponent {options$: {…}, selected: "TEST"}
options$: {label: "TEST", options: Array(2), id: "oil-type"}
selected: "TEST"
__proto__: Object

But inside the table, I get an 'undefined'

Charlie Wallace
  • 1,810
  • 1
  • 15
  • 17
  • Any chance of sharing a stackblitz? I don't see anything immediately wrong, so would be easier if I could see all of the surrounding code as well. – Jesse May 25 '19 at 22:34
  • 1
    @Jesse [Here](https://stackblitz.com/edit/angular-material-table-minimal-example?embed=1&file=src/app/app.component.ts) is the link – burhangoeksen May 26 '19 at 17:08
  • I'm not seeing ```undefined``` anywhere. The stackblitz looks like everything is working as it should be. Can you provide more context? – Jesse May 26 '19 at 21:02
  • Just check the console and if you select something inside the table and click the button you will see it – burhangoeksen May 26 '19 at 21:03

1 Answers1

1

Thanks for the stackblitz.

You actually touch on a very interesting quirk of the Angular framework... Check out this article for detailed information on it, but essentially, template reference variables are accessible only inside their own template. And when we add the *ngIf (or any structural directive for that matter, including *matCellDef), Angular ends up creating a new <ng-template>, making any template reference variables accessible only in that template.

So when you try to reference "drop" outside of the * directives, it shows up as undefined.

Jesse
  • 2,391
  • 14
  • 15
  • Thank you! I unterstand my problem now, but is there any way to get the selected value with something like a service which communicates with the selection component and the component containing the table and the selection component? – burhangoeksen May 26 '19 at 21:43
  • I would look into FormArrays. Also, if you want to do it right, implement ControlValueAccessor on your custom components. I know neither of those is the easy solution, but your future self will thank you. That said... if you're looking for an easier way, just grab the AppDropDown elements as ViewChildren inside the component template using the ```@ViewChildren``` decorator. – Jesse May 26 '19 at 21:55