1

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.

1 Answer 1

3

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 ;)

Sign up to request clarification or add additional context in comments.

3 Comments

I'd like <my-option> to behave like the native <option>, for @Input() a user of this component has to know that they need to write <my-option text="foo"></my-option> instead of <my-option>foo</my-option>
@ThorstenWestheider Sounds reasonable indeed :)
@ThorstenWestheider I tried to remove the nativeElement, but I failed.. I did however came up with a pretty solution for your select -> option thingy :) http://plnkr.co/edit/FupYOwHwa9K7jvmGskFJ?p=preview

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.