8000 Refresh not done properly when triggered by a binding in a directive · Issue #47594 · angular/angular · GitHub
[go: up one dir, main page]

Skip to content
Refresh not done properly when triggered by a binding in a directive #47594
Closed as not planned
@divdavem

Description

@divdavem

Which @angular/* package(s) are the source of the bug?

core

Is this a regression?

No

Description

Here is a component:

@Component({
  selector: 'app-root',
  changeDetection: ChangeDetectionStrategy.OnPush,
  template: `
    <button type="button" (click)="d.toggle()">Toggle</button>
    <button type="button" (click)="state = !state">Toggle by binding</button>
    <ul class="mt-2">
      <li>state = {{ state }}</li>
      <li>d.state = {{ d.stateChange | async }}</li>
      <li>processing = {{ d.processing | async }}</li>
    </ul>

    <div #d="myDirective" [(myDirective)]="state"></div>
  `,
})
export class AppComponent {
  state = false;
}

It uses the following directive:

import { Directive, Input, Output } from '@angular/core';
import { BehaviorSubject } from 'rxjs';

export const createModel = () => {
  const state$ = new BehaviorSubject(true);
  const processing$ = new BehaviorSubject(false);
  const toggle = async (newState = !state$.getValue()): Promise<void> => {
    console.log('Beginning toggle, newState = ' + newState);
    // Note that uncommenting the following line is a workaround for this issue:
    // await Promise.resolve();
    processing$.next(true);
    state$.next(newState);
    await new Promise((resolve) => setTimeout(resolve, 1000));
    processing$.next(false);
    console.log('Ending toggle, newState = ' + newState);
  };

  return {
    state$,
    processing$,
    toggle,
  };
};

@Directive({
  selector: '[myDirective]',
  exportAs: 'myDirective',
})
export class MyDirective {
  private model = createModel();

  @Input('myDirective')
  set state(value: boolean) {
    this.model.toggle(value);
  }

  @Output('myDirectiveChange')
  stateChange = this.model.state$;

  processing = this.model.processing$;

  toggle() {
    return this.model.toggle();
  }
}

When clicking on the "Toggle" button in the component, everything works as expected:

  • The first two lines state and d.state have the same boolean value (the opposite of the previous value), and the third line has processing = true
  • After 1s, the third line switches back to processing = false

When clicking on the "Toggle by binding" button, the same toggle method from the model is triggered, so the same behavior as before would be expected. However, Angular only refreshes the first line (state) and does not update the d.state and processing lines, even though they changed. After 1s, the second line (d.state) is updated with the correct value and the third line did not change at all (now that the value of processing is back to false).

Please provide a link to a minimal reproduction of the bug

https://stackblitz.com/edit/angular-ivy-liytcm?file=src/app/app.component.ts

Please provide the exception or error you saw

There is no error in the console.

Please provide the environment you discovered this bug in (run ng version)

Angular CLI: 14.0.7
Node: 16.17.1
Package Manager: npm 8.15.0 
OS: linux x64

Angular: 14.2.4
... animations, common, compiler, compiler-cli, core, forms
... platform-browser, platform-browser-dynamic, router

Package                         Version
---------------------------------------------------------
@angular-devkit/architect       0.1402.4
@angular-devkit/build-angular   14.2.4
@angular-devkit/core            14.2.4
@angular-devkit/schematics      14.0.7
@angular/cli                    14.0.7
@schematics/angular             14.0.7
rxjs                            7.5.7
typescript                      4.7.4

Anything else?

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions

      0