Thorsten Westheider
Thorsten Westheider

Reputation: 10932

Binding not working for innerHTML in nested component

I'm trying to come up with a custom select control,

<my-select>
   <my-option>Option 1</my-option>
   <my-option>Option 2</my-option>
   ...
</my-select>

which works alright with static text. However, if I introduce bindings

<my-select>
   <my-option *ngFor="let option of options">{{option}}</my-option>
</my-select>

{{option}} always renders as empty string (if I replace {{option}} with, say test then everything is working again). Here are my components:

@Component({
  selector: 'my-select',
  template: `
    <ul>
      <li *ngFor="let option of options">
        {{option.text}}
      </li>
    </ul>
  `
})
export class SelectComponent {
  options: OptionComponent[] = [];
  addOption(option): OptionComponent {
    this.options.push(option);
  }
}

@Component({
  selector: 'my-option',
  template: `
    <div #wrapper>
      <ng-content></ng-content>
    </div>
  `,
  directives: []
})
export class OptionComponent implements AfterContentInit {
  @ViewChild('wrapper') wrapper: ElementRef;
  text: string;
  constructor(private select: SelectComponent) { }
  ngAfterContentInit() {
      let text = this.wrapper.nativeElement.innerHTML;
      this.text = text ? text : 'EMPTY';
      this.select.addOption(this);
  }
}

How can I get this to work?

EDIT: Almost forgot, here's a plnkr showing the problem.

Upvotes: 1

Views: 1232

Answers (1)

Poul Kruijt
Poul Kruijt

Reputation: 71961

You have to use ngAfterViewInit instead of ngAfterContentInit in your OptionComponent before the binding of the view, {{option}}, is done.

export class OptionComponent implements AfterViewInit {
  @ViewChild('wrapper') 
  wrapper: ElementRef;
  text: string;
  constructor(private select: SelectComponent) { }
  ngAfterViewInit() {
      let text = this.wrapper.nativeElement.innerHTML;
      this.text = text ? text : 'EMPTY';
      this.select.addOption(this);
  }
}

plunker

it's pretty frowned upon to use the nativeElement property, A better thing I guess, would be to use @Input() on the OptionComponent, but that's beyond the scope of your question ;)

Upvotes: 3

Related Questions