Search code examples
angulartypescripteventemitter

mat-spinner does not stop spinning


I have a component (dialog-component) where I refer to another component (DATA-component). When I set

isLoaded = false 

(in dialog-component-ts) and I use

this.isLoaded.emit(true);

(in DATA-component), then isLoaded is being set true (in dialog-component-ts), but the mat-spinner does not stop spinning and the loaded data is not being shown. I already use pretty much the same code in other components where it works. When I set

isLoaded = true 

(in dialog-component-ts) then there is no spinner and the data is being displayed. Any ideas what the issue could be?

dialog-component-html:

 <mat-card>
    <div *ngIf="!isLoaded" fxLayout="row" fxLayoutAlign="center center" class="loading">
      <mat-spinner></mat-spinner>
    </div>
    <app-data *ngIf="selectedDialogData === enum1" [fxShow]="isLoaded"
                       (title)="onComponentTitleChange($event)"
                       (isLoaded)="onComponentReadyStateChange($event)"
                       (dialogDataChanged)="onSelectedDialogDataChange($event)">
    </app-data>
 </mat-card>

dialog-component-ts:

@Component({
  selector: 'app-dialog',
  templateUrl: './dialog.component.html',
  styleUrls: ['./dialog.component.scss'],
  changeDetection: ChangeDetectionStrategy.OnPush
})


export class DialogComponent {

  constructor(
    @Inject(MAT_DIALOG_DATA) public dialogData: SomeModel) { }

  public isLoaded = false;
  
...

  public onComponentReadyStateChange(state) {
    this.isLoaded = state;
  }
...

data-compontent-ts:

@Component({
  selector: 'app-data',
  templateUrl: './data.component.html',
  styleUrls: ['./data.component.scss'],
  changeDetection: ChangeDetectionStrategy.OnPush
})
export class WorkingtypeDataComponent implements OnInit {

  @Output() title = new EventEmitter<string>();
  @Output() isLoaded = new EventEmitter<boolean>();
  @Output() dialogDataChanged = new EventEmitter<EnumList>();

  constructor(@Inject(MAT_DIALOG_DATA) public dialogData: SomeModel,
              private dialogRef: MatDialogRef<DialogComponent>,
              private formBuilder: FormBuilder,
              private Service: SomeService,
              private dialog: MatDialog) { }


  ngOnInit(): void {
    this.isLoaded.emit(false);
    this.currentElement = this.dialogData.changeElement;
    this.alreadyExistingElementNames = this.dialogData.alreadyExistingElementNames;
    this.isEditing = this.currentElement.name != null;
    const title = `texts.${this.isEditing ? 'edit' : 'add'}`;
    this.title.emit(title);
    this.isLoaded.emit(true);
  }

Solution

  • When using ChangeDetection.OnPush Angular only runs change detection when @Input changes are detected.

    To act on child Outputs you need to manually trigger a change detection cycle.

    For example using this.cdr.detectChanges()

    Guide