Home > database >  how to pass either a @input label prop or the content as label to a angular button component?
how to pass either a @input label prop or the content as label to a angular button component?

Time:01-28

I am trying to use a label that can come to the component as an @Input() or as content to a button:

@Component({
  selector: 'button[app-button]',
  template: `
  <ng-container *ngIf="label">
    <ng-content>{{label}}</ng-content>
  </ng-container>
  <ng-container *ngIf="!label">
    <ng-content></ng-content>
  </ng-container>
  `,
})

Problem is that the above does work because ng-content can not have content. Any ideas how to solve this without wrapping the button in another host element?

EDIT: I would like to use it as follows.

<!-- this should work -->
<button app-button>I am a label</button>
<!-- this also should work -->
<button app-button label="Another label"></button>
<!-- should work -->
<button app-button [label]="'Wow a Label'"></button>

CodePudding user response:

Is this what you want??

@Component({
  selector: 'button[app-button]',
  template: `
  <ng-container *ngIf="label">
      {{label}
  </ng-container>
  <ng-container *ngIf="!label">
    <ng-content></ng-content>
  </ng-container>
  `,
})

CodePudding user response:

What you actually want is not a Component, but a Directive. If you provide an attribute selector the provided template will be ignored. Inside your Directive you can get access to the host element via ElementRef. So what you want, could be implemented like this:

@Directive({
  selector: 'button[app-button]',
})
export class ButtonDirective implements OnInit {
  @Input()
  label: string;

  constructor(
    private el: ElementRef,
  ) {
  }

  ngOnInit() {
    if (this.label) {
      this.el.nativeElement.innerText = this.label;
    }
  }
}

You could also take a look at the documentation for attribute directives. If you need to modify the host element you could also look into structural directives.

That being said, this doesn't feel like the angular way to do things. I would consider just building an <app-button></app-button> component with this feature.

  • Related