springbo
springbo

Reputation: 1096

angular 2 equivalent of vuejs v-bind

As title implies i'm looking for a way to bind an object with multiple properties to component @Inputs without having to explicitly write all of them

Let's say I have this object

let params = {
    delta: 0.2,
    theta: 2.3,
    sigma: 'foo',
}

Instead of having to bind all of them individually like this

<my-component
    [delta]="params.delta"
    [theta]="params.theta"
    [sigma]="params.sigma"/>

I would like bind all of them at once.

<my-component [someDirectiveIDontKnow]="params"/>

How can i do this?

Found a link to a previously asked question but couldn't get that to work properly.

Edit: I'm not asking how to bind @Inputs. Imagine that the component I'm rendering has 40 @Inputs and I'm NOT allowed to rewrite it to just accept one @Input that could contain all the params.

So writing a template that uses this component gets really ugly and big.

....
<my-component
  [param1]="params.param1"
  [param2]="params.param2"
  [param3]="params.param3"
  [param4]="params.param4"
  [param5]="params.param5"
  [param6]="params.param6"
  [param7]="params.param7"
  [param8]="params.param8"
  [param9]="params.param9"
  [param10]="params.param10"
  [param11]="params.param11"
  [param12]="params.param12"
  [param13]="params.param13"
  [param14]="params.param14"
  ... and so on ....
/>
....

Upvotes: 0

Views: 1557

Answers (2)

Samantha Adrichem
Samantha Adrichem

Reputation: 862

In my opinion, It would be best to define them all in a model

You would start with the following model

params.model.ts

import {SomeOtherModel} from './some-other.model'

export interface ParamsModel {
    paramName1: string;
    paramName2?: string;
    paramName3?: number;
    paramName4: SomeOtherModel;
}

Then in your component, you can force your input to take a specific model argument

my.component.ts

import {ParamsModel} from './params.model';

@Component({..})
class MyComponent {
  @Input() params: ParamsModel;
}

app.component.html

<my-component params="paramsModel"></my-component>

app.component.ts

import {ParamsModel} from './params.model';

@Component({..})
class AppComponent implements OnInit {
    paramsModel: ParamsModel;


    ngOnInit(): void {
        this.paramsModel = <ParamsModel>{someValue: someValue};
    }
}

this way you have full code completion.

do note though! Angular does not deepwatch the contents, so changing the contents inside the Params object, will still have the same object ID in javascript, causing angular to not see the changes.

There are a few work-around for this

1: Bind every param (this is exactly what you do not want)

2: When changing contents of the model, destroy the instance and create a new instance everytime, you could do this by adding a constructor in the model and convert it olike this code

export class ParamsModel {
    paramName1: string;
    paramName2?: string;
    paramName3?: number;
    paramName4: SomeOtherModel;

    constructor(config?: ParamsModel) {
        Object.assign(this, config);
    }
}

// first init
this.paramsModel = new ParamsModel(<ParamsModel>{someValue: someValue});

// updated init
this.paramsModel = new ParamsModel(this.paramsModel);
this.paramsModel.changedValue = changedValue; // (could also use an extend function on original params model)

3: Create an observer with events and trigger update events on the other side

4: use ngDoCheck to perform your own check if the contents changed

Upvotes: 1

Avin Kavish
Avin Kavish

Reputation: 8937

There is no generic directive to pass input properties in Angular. However, Angular supports binding any valid JavaScript type be it objects, arrays or primitives.

In the template

<my-component [params]="params"/>

In the class you have to use the @Input decorator to mark an object as an input. You can access it's value in any of the lifecycle hooks, some shown below. Note that params will not be set inside the constructor as view binding is performed after the class is instantiated.

class MyComponent {
  @Input()
  params: any

  constructor() { }   // <-- params not set

  ngOnChanges() { } // <-- anytime params changes

  ngOnInit() { } // <-- once when the component is mounted

}

Upvotes: 0

Related Questions