1

I am working on an Angular app using PrimeNG. I am asking if I can conditionally add a PrimeNG component attribute based on the value of a property. Into my HTML page I have something like this:

<span [ngClass]="{'isMobileCalendar' : (isMobile2 | async)}">
    <p-calendar monthNavigator="true" 
                yearRange="1990:2060" 
                yearNavigator="true" 
                formControlName="date"
                [touchUI]="true"
                [style]="{'width':'85%'}">
    </p-calendar>     
</span>

As I can see at the moment I have this attribute set to true: [touchUI]="true". I also have this (isMobile2 | async) variable defined in my Angular component and obtained using the |async.

I need to implement the following behavior:

  • If (isMobile2 | async) value is true --> set: [touchUI]="true"
  • If (isMobile2 | async) value is false --> set: [touchUI]="false"

Is it possible to implement this behavior inline instead to use ngIf and define twice p-calendar components (based on the value of isMobile2 | async value)? If it could be done inline it will be nice and neat

AndreaNobili
  • 40,955
  • 107
  • 324
  • 596
  • i am not 100% sure about the async pipe but you can use [attr.touchUI]="(isMobile2 | async)" i think. What happens when you just use [touchUI]="isMobile2 | async"? – thecOdemOnkey Jun 08 '21 at 10:02

2 Answers2

1

Yes but since the emission from the observable is a boolean, you'd need to use a TemplateRef to dynamically send the value and reuse it.

<ng-container *ngTemplateOutlet="template; context: {$implicit: (isMobile2 | async)}"></ng-container>

<ng-template #template let-isMobile2>
<!-- 
`isMobile2` here is local scoped to `ng-template` and refers to the declaration in `let-isMobile2`. 
For the record it could take other names as well. 
Eg. `let-myCondition` - in this case, the binding would be `[class.isMobileCalendar]="myCondition"` and `[touchUI]="myCondition"`
-->

  <span [ngClass]="{'isMobileCalendar' : isMobile2}">
    <p-calendar monthNavigator="true" 
                yearRange="1990:2060" 
                yearNavigator="true" 
                formControlName="date"
                [touchUI]="isMobile2"
                [style]="{'width':'85%'}">
    </p-calendar>     
  </span>
</ng-template>

For conditionally applying a single class, you could also try the following instead of ngClass

<span [class.isMobileCalendar]="isMobile2">
  ...
</span>
ruth
  • 29,535
  • 4
  • 30
  • 57
0

Have you tried below?

<span [ngClass]="{'isMobileCalendar' : (isMobile2 | async)}">
    <p-calendar monthNavigator="true" 
                yearRange="1990:2060" 
                yearNavigator="true" 
                formControlName="date"
                [touchUI]="(isMobile2 | async)"
                [style]="{'width':'85%'}">
    </p-calendar>     
</span>

Edit 1: How about this one ?

 <ng-container *ngIf="{isMobile:(isMobile2 | async)} as pageState">
    <span [ngClass]="{'isMobileCalendar' : pageState.isMobile}">
        <p-calendar monthNavigator="true" 
                    yearRange="1990:2060" 
                    yearNavigator="true" 
                    formControlName="date"
                    [touchUI]="pageState.isMobile"
                    [style]="{'width':'85%'}">
        </p-calendar>     
    </span>
 </ng-container>
Rey
  • 51
  • 3
  • This would instantiate two subscriptions to the `isMobile2` observable. If it's a cold observable, it'd be triggered twice. – ruth Jun 08 '21 at 10:12
  • This would not render the `` if the boolean emitted by the observable is `false` since `*ngIf` directive would fail. Please check my answer for one workaround using `TemplateRef`. – ruth Jun 08 '21 at 10:21
  • I was wrong. I didn't notice you were instantiating the local variable `pageState` as an object. Actually this would also work and would be simpler than my solution. – ruth Jun 08 '21 at 10:33