Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular: How to use the directive microsyntax with cdkConnectedOverly?

According to the Angular docs, there is a microsyntax that can be used with structural directives.

So I have some code that is working with the cdkConnectedOverlay directive while using the 'long hand' form:

  <ng-template 
    cdkConnectedOverlay 
    [cdkConnectedOverlayOrigin]="savedSearchTrigger" 
    [cdkConnectedOverlayOpen]="savedSearchToggle.checked"
    [cdkConnectedOverlayHasBackdrop]="true" 
    [cdkConnectedOverlayBackdropClass]="'transparentOverlayBackdrop'">
    My overlay contents!
  </ng-template>

After reading about the microsyntax, it seems I should be able to shorten my code to:

  <ng-template 
    *cdkConnectedOverlay="origin: savedSearchTrigger; open: savedSearchToggle.checked; hasBackdrop: true; backdropClass: 'transparentOverlayBackdrop'">
     My overlay contents!
  </ng-template>

However, this isn't compiling. And is giving me the error Cannot read the property 'toUpperCase' of undefined

I'm wondering if the fact I'm trying to use the microsyntax on an ng-template is the culprit.

What am I doing wrong? Is there a work around?

like image 469
checketts Avatar asked Dec 07 '25 10:12

checketts


1 Answers

Angular compiler expects that the microsyntax will start either with value

*cdkConnectedOverlay="cdkConnectedOverlayValue; otherProp: otherPropValue...."

or with variable:

*cdkConnectedOverlay="let x; otherProp: otherPropValue...."

Since CdkConnectedOverlay doesn't have @Input with name CdkConnectedOverlay then you cannot use syntax like:

*cdkConnectedOverlay="1;origin: savedSearchTrigger;...

To work around it you could create a directive with [cdkConnectedOverlay] selector and the same @Input property but I would go with the first solution:

<ng-container *cdkConnectedOverlay="let x;origin: savedSearchTrigger; open: opened; 
                 hasBackdrop: true; backdropClass: 'transparentOverlayBackdrop'">

Despite the fact that it will compile you can notice that your content is not displayed. To fix it you should use <ng-container *cdkConnectedOverlay instead of <ng-template *cdkConnectedOverlay so that My overlay contents! content won't be wrapped in additional ng-template

Finally, take a look at Ng-run Example

Update

Note, that sugar (*) syntax does not support @Output therefore the event won't be fired in the following code:

<ng-container *cdkConnectedOverlay="..." (backdropClick)="opened = false">

To work around it you could pass some handler as @Input by creating additional directive like:

@Directive({
  selector: '[cdkConnectedOverlayBackdropClick]'
})
export class ConnectedOverlayBackdropClick {
  @Input('cdkConnectedOverlayBackdropClick') backDropHandler: Function;

  @HostListener('backdropClick')
  backdropClick() {
    this.backDropHandler();
  }
}

And then catch event in component:

component.html

<ng-container *cdkConnectedOverlay="let item; origin: savedSearchTrigger; open: opened; 
hasBackdrop: true; backdropClass: 'transparentOverlayBackdrop'; backdropClick: close">

component.ts

close = () => {
  this.opened = false;
}

Ng-run Example

like image 85
yurzui Avatar answered Dec 10 '25 09:12

yurzui