7

How do I pass attributes from a parent component to their child components' class constructor in Angular 2?

Half of the mystery is figured out, as attributes can be passed to the view without problem.

/client/app.ts

import {Component, View, bootstrap} from 'angular2/angular2';
import {Example} from 'client/example';

@Component({
  selector: 'app'
})
@View({
  template: `<p>Hello</p>
    <example [test]="someAttr"
      [hyphenated-test]="someHyphenatedAttr"
      [alias-test]="someAlias"></example>
    `,
  directives: [Example]
})
class App {
  constructor() {
    this.someAttr = "attribute passsed to component";
    this.someHyphenatedAttr = "hyphenated attribute passed to component";
    this.someAlias = "attribute passed to component then aliased";
  }
}

bootstrap(App);

/client/example.ts

import {Component, View, Attribute} from 'angular2/angular2';

@Component({
  selector: 'example',
  properties: ['test', 'hyphenatedTest', 'alias: aliasTest']
})
@View({
  template: `
    <p>Test: {{test}}</p>
    <!-- result: attribute passsed to component -->
    <p>Hyphenated: {{hyphenatedTest}}</p>
    <!-- result: hyphenated attribute passed to component -->
    <p>Aliased: {{alias}}</p>
    <!-- result: attribute passed to component then aliased -->

    <button (click)="attributeCheck()">What is the value of 'this.test'?</button>
    <!-- result: attribute passed to component -->
  `
})
/*******************************************************************
* HERE IS THE PROBLEM. How to access the attribute inside the class? 
*******************************************************************/
export class Example {
  constructor(@Attribute('test') test:string) {
     console.log(this.test); // result: undefined
     console.log(test); // result: null
  }
  attributeCheck() {
    alert(this.test);
  }
}

To re-iterate:

How can I access an attribute inside the child component's class passed in from the parent component?

Repo

Michael
  • 1,453
  • 3
  • 20
  • 28
shmck
  • 5,129
  • 4
  • 17
  • 29

2 Answers2

11

Updated to beta.1

You can use ngOnInit for this

@Component({
  selector: 'example',
  inputs: ['test', 'hyphenatedTest', 'alias: aliasTest'],
  template: `
    <p>Test: {{test}}</p>
    <!-- result: attribute passsed to component -->
    <p>Hyphenated: {{hyphenatedTest}}</p>
    <!-- result: hyphenated attribute passed to component -->
    <p>Aliased: {{alias}}</p>
    <!-- result: attribute passed to component then aliased -->

    <button (click)="attributeCheck()">What is the value of 'this.test'?</button>
    <!-- result: attribute passed to component -->
  `
})
export class Example {

  ngOnInit() {
    console.log(this.test);
    this.attributeCheck();
  }

  attributeCheck() {
    alert(this.test);
  }
}
Eric Martinez
  • 31,277
  • 9
  • 92
  • 91
0

If you want to have access to properties values in child component you can:

import {Component, View, Attribute} from 'angular2/angular2';

@Component({
  selector: 'example',
  properties: ['test', 'hyphenatedTest', 'alias: aliasTest']
})
@View({
  template: `
    <p>Test: {{_test}}</p>
    <!-- result: attribute passsed to component -->
    <p>Hyphenated: {{_hyphenatedTest}}</p>
    <!-- result: hyphenated attribute passed to component -->
    <p>Aliased: {{_alias}}</p>
    <!-- result: attribute passed to component then aliased -->
  `
})
export class Example {
  _test: string;
  _hyphenatedTest: any; //change to proper type
  _alias: any; //change to proper type

  constructor() {
  }

  set test(test) {
    this._test = test;
  }

  set hyphenatedTest(hyphenatedTest) {
    this._hyphenatedTest = hyphenatedTest;
  }

 set alias(alias) {
    this._alias = alias;
  }

}

set method is run when the value of property changes. Value is passed to your local variable on which you can operate in component.

Important things:

  • set method is always executed after constructor
  • I don't know why but the name of parameter in set method must be same as name of this method (so it means it must be the same as name of property)
haz111
  • 764
  • 1
  • 6
  • 17
  • This is very helpful to know. Thank you! However, as the `set` method is run after the constructor, I still don't have access to `this.test` when the class is loaded. There must be a solution. – shmck Aug 05 '15 at 10:22
  • I've edited the solution above to show that the `@Attribute` way also sets `this.test`, however also after the constructor has loaded. – shmck Aug 05 '15 at 10:24
  • I was searching solution of this problem last week but nothing worked. I hope that it exists. `set` method is poor replacement - unfortunately it doesn't solve all problems. – haz111 Aug 05 '15 at 10:45
  • Now that I think of it, I could potentially move my constructor code into the `set` block. It would actually work, but there must be a better way. – shmck Aug 05 '15 at 10:52