Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to wrap an Angular Component and pass ng-template from outer to inner component

I am using Angular 5 and trying to wrap ng-select in a custom component. My reason is to encapsulate it so it could be easily replaced if needs be. If there is a better way to do this please let me know.

I created a custom component and I have various @Inputs() which in turn are passed to the inner ng-select. This all works fine.

My problem is how to correctly pass ng-select custom templates to the wrapped ng-select?

Here's an example of what I have so far, I have left out some inputs for simplicity.

This is how I call the wrapper passing in the custom templates:

 <app-wrapper-select
    [items]="cars"
    [(selected)]="selectedCars">

    <ng-template #labelTemplate ng-label-tmp let-item="item">
      <span class="ng-value-label">LABEL {{item.metadata.name}}</span>
      <span class="ng-value-icon right" aria-hidden="true">×</span>
    </ng-template>

    <ng-template #optionTemplate ng-option-tmp let-item="item">
      <span class="ng-value-label">OPTION {{item.metadata.name}}</span>
      <span class="ng-value-icon right" aria-hidden="true">×</span>
    </ng-template>

  </app-wrapper-select>

In the wrapper component I declare the templates as follows:

@ContentChild('labelTemplate', { read: TemplateRef }) labelTemplate: TemplateRef<any>;
@ContentChild('optionTemplate', { read: TemplateRef }) optionTemplate: TemplateRef<any>;

Here's the wrapper components html:

<ng-select
  [items]="items"
  [(ngModel)]="selected">

  <ng-template ng-label-tmp let-item="item">
    <ng-container *ngTemplateOutlet="labelTemplate; context:{item: item}"></ng-container>
  </ng-template>

   <ng-template ng-option-tmp let-item="item">
    <ng-container *ngTemplateOutlet="optionTemplate; context:{item: item}"></ng-container>
  </ng-template>

</ng-select>

The above does kind of render the templates but the labels and options have all their styles missing and just appear as text on a white background.

I must be missing something, how can I get the styles to render properly?

Another problem is ng-select has a close button on each label to remove it from the selected items and an associated clear() method - but when I use it in my template outside of ng-select it is not recognised e.g.

        <ng-template #labelTemplate ng-label-tmp let-item="item" let-clear="clear">
          <span class="ng-value-label">LABEL {{item.metadata.name}}</span>
          <span class="ng-value-icon right" (click)="clear(item)" aria-hidden="true">×</span>
        </ng-template>

How can I use the clear() in a ng-template outside of ng-select, is there some way I can get a reference to it and call it?

Thanks.

like image 793
user1810292 Avatar asked Jan 02 '23 01:01

user1810292


1 Answers

OK I got it working here's solution in case someone gets confused like I did. In IntelliJ when template input variables are functions it doesn't recognise them and says they are not callable. It does compile fine though. This also happens with ngBootstrap modals and the close and dismiss methods. Here's the ng-template I used which is now working

<app-wrapper-select
    [items]="cars"
    [(selected)]="selectedCars">

    <ng-template #labelTemplate ng-label-tmp let-item="item" let-clear="clear">
      <span class="ng-value-label">{{item.metadata.name}}</span>
      <span class="ng-value-icon right" (click)="clear(item)" aria-hidden="true">×</span>
    </ng-template>

    <ng-template #optionTemplate ng-option-tmp let-item="item">
      <span class="ng-value-label">{{item.metadata.name}}</span>
    </ng-template>
</app-wrapper-select>


<ng-select
    [items]="items"
    [(ngModel)]="selected">

    <ng-template ng-label-tmp let-item="item" let-clear="clear">
      <ng-container *ngTemplateOutlet="labelTemplate; context:{item: item, clear: clear}"></ng-container>
    </ng-template>

    <ng-template ng-option-tmp let-item="item">
      <ng-container *ngTemplateOutlet="optionTemplate; context:{item: item}"></ng-container>
    </ng-template>
</ng-select>
like image 175
user1810292 Avatar answered May 12 '23 21:05

user1810292