Search code examples
htmlangulardomwizard

Focus on input on each step of Angular wizard


Environment

  • Angular 8
  • AZ-Wizard

Requirement

We need to have the first (or a specific) element get focused when the user moves to a step. Each step will have its own different elements (input, button, dropdown etc) which should get auto-focus so user doesn't have to manually click the one to start the flow.

Code tried

  1. Use autofocus tag on elements. This doesn't works apart from the 1st element as with wizard, the whole set of steps is a single DOM.
  2. Use ngOnViewEdit event and ViewChild on desired element in each step's component to set the focus

    ngOnViewEdit() { var emailElement = (this.email.nativeElement); if (emailElement) { emailElement.focus(); } else alert("Email element not found"); } This also doesn't works somehow. Also tried with wrapping the method's body with a setTimeout call with timeout varying from 0 to 1000.

  3. In the wizard's stepEnter try to access the ViewChild and do the focus attempt. This also failed to work

Component UI

`<aw-wizard-step (stepEnter)="setFocus()">
    <app-cost-impact></app-cost-impact>
</aw-wizard-step>`

Component TS

setFocus() { var emailComponent = <AddEmailComponent><unknown>this.wizard.currentStep; var emailElement = (<HTMLInputElement>emailComponent.email.nativeElement); if (emailElement) { emailElement.focus(); } else alert("Email element not found"); }

Challange

We need to figure out some way to access the elements for each step and make it generic enough to handle all steps


Solution

  • Try passing the id of the input element to setFocus method and change the setFocus method as below:

      setFocus (id: string) {
            setTimeout(() => {
              var inputEl= document.getElementById(id);
              if (inputEl) {
                document.getElementById(inputEl).focus();
              }
            }, 0);
          }
    
    

    Component UI:

    
        `<aw-wizard-step (stepEnter)="setFocus('inputElementId')">
            <first-component></first-component>
        </aw-wizard-step>
        <aw-wizard-step (stepEnter)="setFocus('anotherElementId')">
            <second-component></second-component>
        </aw-wizard-step>
        `
    
    

    In this way, you can just declare the setFocus method once in the corresponding typescript file and can use it for any number of components by passing in the id of the input element.