ionic-team / ionic-framework

A powerful cross-platform UI toolkit for building native-quality iOS, Android, and Progressive Web Apps with HTML, CSS, and JavaScript.
https://ionicframework.com
MIT License
51.02k stars 13.51k forks source link

bug: Can't use IonFab's activated property in conditions on template #19361

Closed matheuskt closed 4 years ago

matheuskt commented 5 years ago

Can't use IonFab's activated property in conditions on template

Ionic version:

[x] 4.x

Current behavior:

GIF: https://im2.ezgif.com/tmp/ezgif-2-7ec13650fe23.gif

When trying to use the IonFab's / IonFabList's activated property as a condition to any element on the template it doesn't update as expected.

The property actually updates to true/false but the template acts strangely.

Expected behavior:

When clicking on a Fab Button the activated property updates to the current state and the templates condition updates accordingly.

Steps to reproduce:

1) Create a new Ionic 4.x application. 2) Create a Fab Container with a FabButton and a FabList with buttons inside it. And use ViewChild to get a reference from the FabContainer. 4) Use the Fab container activated property as a render condition to any element on the template.

Related code:

Sample repository: https://github.com/matheuskt/ionic-fab-issue

home.page.ts

import { Component, ViewChild } from '@angular/core';
import { IonFab } from '@ionic/angular';

@Component({
  selector: 'app-home',
  templateUrl: 'home.page.html',
  styleUrls: ['home.page.scss'],
})
export class HomePage {

  @ViewChild('fabRef', { static: false }) fabRef: IonFab;

  constructor() {}

  public onFabClick() {
    console.log('FAB active?', this.fabRef.activated, this.fabRef);
  }

}

home.page.html

<ion-header>
  <ion-toolbar>
    <ion-title>
      Ionic Blank
    </ion-title>
  </ion-toolbar>
</ion-header>

<ion-content>

  <p *ngIf="fabRef.activated">FAB active</p>
  <p *ngIf="!fabRef.activated">FAB inactive</p>

  <ion-fab #fabRef vertical="bottom" horizontal="end">
    <ion-fab-button (click)="onFabClick()">
      <ion-icon name="add"></ion-icon>
    </ion-fab-button>
    <ion-fab-list side="top">
      <ion-fab-button>
        <ion-icon name="images"></ion-icon>
      </ion-fab-button>
      <ion-fab-button>
        <ion-icon name="images"></ion-icon>
      </ion-fab-button>
      <ion-fab-button>
        <ion-icon name="images"></ion-icon>
      </ion-fab-button>
    </ion-fab-list>
  </ion-fab>

</ion-content>

Other information:

Ionic info:

Ionic:

   Ionic CLI                     : 5.2.7 
   Ionic Framework               : @ionic/angular 4.9.0
   @angular-devkit/build-angular : 0.801.3
   @angular-devkit/schematics    : 8.1.3
   @angular/cli                  : 8.1.3
   @ionic/angular-toolkit        : 2.0.0

Utility:

   cordova-res : 0.5.1 (update available: 0.6.0)
   native-run  : 0.2.8 

System:

   NodeJS : v10.15.3
   npm    : 6.9.1
   OS     : Linux 5.0
cmer4 commented 4 years ago

Yes it seems like the issue can be reproduced if you do sort of a long press / click on the button. Then I am able to confuse the component to show activated false state when in fact it should be active. https://stackblitz.com/edit/ionic-4-template-y9ypf3

So in the above stackblitz I can "mousedown" on the FAB and wait 2 secs until I release mouse button (mouseup). This way I can get it into confusing state. If I keep doing perfect click (mousedown/mouseup) I think it works as intended.

matheuskt commented 4 years ago

Haven't updated it in a while, but came back to work on the project that has this issue and it probably has something to do with Angular change detection.

A simple workaround for this is to use the ChangeDetectorRef's detectChanges() method.

home.page.html

<div *ngIf="fab.activated" class="fab-backdrop"></div>

<ion-fab (click)="detectChanges()" #fab vertical="bottom" horizontal="end" slot="fixed">

home.page.ts

constructor(private _changeRef: ChangeDetectorRef) { }

detectChanges() {
    setTimeout(() => {
      this._changeRef.detectChanges();
    });
}

For another strange reason setTimeout() is necessary here or it wont work properly.

Apro123 commented 4 years ago

Is there any update on this?

zabalit commented 4 years ago

Same problem here

ionitron-bot[bot] commented 4 years ago

Thanks for the issue! This issue is being locked to prevent comments that are not relevant to the original issue. If this is still an issue with the latest version of Ionic, please create a new issue and ensure the template is fully filled out.