storybook
storybook copied to clipboard
Wrong rendering of Angular component (*ngIf)
Describe the bug
A simple component with an *ngIf
has unexpected behaviour. You can reproduce the issue from this project.
Lets say I create a wrapper over ionic button component.
<ion-button
[fill]="buttonStyle"
[expand]="expand"
[disabled]="disabled"
(click)="onClick($event)"
>
<ng-container *ngIf="isLoading === false; else loadingSpinner">
{{ buttonText }}
</ng-container>
<ng-template #loadingSpinner>
<ion-spinner name="crescent"></ion-spinner>
</ng-template>
</ion-button>
import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
@Component({
selector: 'app-button',
templateUrl: './button.component.html',
styleUrls: ['./button.component.scss']
})
export class ButtonComponent {
@Input() buttonText: string;
@Input() buttonStyle:
| 'clear'
| 'outline'
| 'solid'
| 'default'
| undefined = 'solid';
@Input() disabled = false;
@Input() expand: 'full' | undefined = undefined;
@Input() isLoading = false;
@Output() clickEvent: EventEmitter<MouseEvent> = new EventEmitter<
MouseEvent
>();
constructor() {}
onClick(event: MouseEvent): void {
this.clickEvent.emit(event);
}
}
import { Meta, Story } from '@storybook/angular';
import { action } from '@storybook/addon-actions';
import { ButtonComponent } from './button.component';
export default {
title: 'ion-button-wrapper',
component: ButtonComponent,
argTypes: {
buttonStyle: {
control: {
type: 'select',
options: ['clear', 'outline', 'solid', 'default', undefined],
},
},
expand: {
control: {
type: 'select',
options: ['full', undefined],
},
},
isLoading: {
control: {
type: 'boolean'
}
}
},
} as Meta;
const Template: Story = (args: ButtonComponent) => ({
props: { ...args },
component: ButtonComponent,
});
export const Basic: Story = Template.bind({});
Basic.storyName = 'Basic';
Basic.args = {
buttonText: 'Button Text',
clickEvent: (event) => {
action('Button Click Event')(event);
},
};
The issue is with isLoading
control. The component should display one spinner, but instead, it shows two for some reason.
To Reproduce
Playaround with isLoading
control of ion-button-wrapper of this project
Expected behavior There should be a single spinner spinning in the button.
Screenshots
Automention: Hey @MaximSagan @kroeder, you've been tagged! Can you give a hand here?
Should be fixed by #12382. I patched my node_modules to set the props in NgZone
, similar to how I did in that PR and couldn't reproduce the issue any more.
I couldn't reproduce it in chrome. Your second screenshot looks like you are using Firefox, so I tried it and was able to reproduce the issue.
The ion-spinner
implementation is doing a few unique things with how they write components, so I didn't try to track down what exactly is causing the problem. My assumption is that they are registering some events that rely on NgZone
to trigger change detection. Maybe Chrome is completing the event before the current change detection tick completes and Firefox is completing it after the current tick. It is only a guess though. Currently inputs changed by a control are not set inside NgZone
, so an events registered as a result would also not be hooked by NgZone
, unless it is manually entered.
Hi everyone! Seems like there hasn't been much going on in this issue lately. If there are still questions, comments, or bugs, please feel free to continue the discussion. Unfortunately, we don't have time to get to every issue. We are always open to contributions so please send us a pull request if you would like to help. Inactive issues will be closed after 30 days. Thanks!