11
votes

We are using Angular 5 and material design and creating our own components with helper methods for various functions (i.e. dynamic column generation for mat-table).

I'd like a way to pass unknown attributes from my parent component onto my child component. This is easy in React, for example:

App class render

<MyDatatable knownVar="1" otherKnownVar="2" unknownButKnownToChildVar="3" />

MyDataTable render

<MatComponent {...this.props} />

This way if MatComponent ever updated what attributes it took in, MyDataTable wouldn't have to be updated. I've looked at the @Input decorator but this doesn't seem to facilitate unknown variables.

One solution I've thought of is to just pass in an object and account for that object via @Input but I don't like this because I would like the angular-material component documentation to accurately reflect how a developer should be using my MyDataTable component.

Short version of my question: How do I pass unaccounted for attribute-level data to a child component in Angular 5?

2
This doesn't exist in Angular, and it wouldn't work with AoT. - Ingo Bürk
If you don't want to change the child component when the data changes, you surely must know what sort of data is being provided. Like a person component would receive a person as input. You can provide as many inputs as you want though. So you could define all your known inputs, and define one extra that does what you described in your solution. - Jusmpty
Can't unknown variable be of Object type, so that in future it can contain attributes as much as required in form of Object's properties? - khush
Technically yes, and that's what I covered in the proposed solution section of my question. This however would not let you supply attributes on the component of any name. <MyAngComponent unknownAttribute="1"> would be impossible to pass through to a child component without specifically supplying an @Input selector for unknownAttribute in MyAngComponent class - Vap0r
after a year, were you able to get around this? - Alvin

2 Answers

0
votes
<div class="example-container mat-elevation-z8">
      <table mat-table #table [dataSource]="dataSource">

        <!--- Note that these columns can be defined in any order.
              The actual rendered columns are set as a property on the row definition" -->

        <!--  Column -->
        <ng-container matColumnDef="column">
          <th mat-header-cell *matHeaderCellDef> column </th>
          <td mat-cell *matCellDef="let element"> {{element.symbol}} </td>
        </ng-container>

        <tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
        <tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
      </table>
    </div>

Sample.html

simply pass your datasource object which might come either from parent or from child component.

dataSource = DATA ;

Hope u got my point or you require something different. As per your question dynamic data insertion to your table must bind to controller part .In term of angular if your datasource model get updated by child component as well as parent component.It render data as updation occur.

Show the code for your parent and child component data If possible? Thanks

0
votes

The one way i can think of doing what you want with the Input decorator that Angular provides is by passing a JS Object (any) into the Component Input and depending on the properties, execute the desirable code. Example:

my-component.component.ts

import { Component, OnInit, Input } from '@angular/core';

@Component({
  selector: 'my-component',
  templateUrl: './my-component.component.html',
  styleUrls: ['./my-component.component.css']
})
export class MyComponentComponent implements OnInit {
  @Input() data: any;
  constructor() { }
  ngOnInit() { }
}

app.component.html

<my-component [data]="{data: 2, extraData: 3}"></my-component>

In that case you can add n* number of properties in the input data. There isn't any implementation for passing unknown number of attributes into the component.

An other cool thing you could also do is inside your component you could actually have some default values and also expect some more. Like the example here:

app.component.html

<my-component [data]="{name: 'John', surname: 'Doe'}"></my-component>

my-component.component.ts

import { Component, OnInit, Input } from '@angular/core';

@Component({
  selector: 'my-component',
  templateUrl: './my-component.component.html',
  styleUrls: ['./my-component.component.css']
})
export class MyComponentComponent implements OnInit {
  @Input() data: any;
  constructor() { }
  ngOnInit() {
    this.data = {
      name: "John",
      surname: "Doe",
      origin: "UK",
      ...this.data
    }
  }
}

my-component.component.html

<div *ngIf="data.phone">
  Phone Number: {{ data.phone }}
</div>

Or even make some kind of Object.keys(this.data) and loop over the data properties and print the correct html. That way you can have some default values for the known properties and even expect some more unknown properties.

Hope I've been of any help.