Search code examples
angularngrxngrx-effects

NGRX set focus on Input via @Effect


I've got a Login component.

When it loads, it grabs Username from local storage.

If exists, I would then like to have the focus be set on the Password field.

Currently, I'm doing it in the store subscription.

@ViewChild('passfield', { static: false }) passfield: ElementRef;

// ...

this.store.select('login')
  .subscribe(state => {
    this.model.user = state.username;
    if (this.model.user) {
      // focus on pass field if user is not empty
      setTimeout(() => this.passfield.nativeElement.focus(), 0); // <---
    }
  });

I want to move that focus to an effect and clear logic from my component.

  • Can it be done?
  • Can we use view child in effect?
  • Do we want to do it ? is there a better approach?

Solution

  • I would rewrite things slightly, but definitely keep the logic in the component:

    private destroy$ = new Subject<boolean>();
    
    this.store.select('login').pipe(
      takeUntil(this.destroy$),
      filter(user => user.username),
      tap(() => this.passfield.nativeElement.focus())
    ).subscribe();
    
    ngOnDestroy() {
      this.destroy$.next(true);
    }
    

    I don't think using a side effect to check something in the store from a component to then play with the DOM of the same component is wise. Possible, but unnecessarily complicated.

    EDIT: NGRX for state management, components as pure reflections of state. The component should be the one choosing how it interprets a given state.