Angular 5模拟输入控件上的按键

时间:2018-06-19 16:23:51

标签: angular typescript angular-directive

我正在尝试模拟在输入控件上按Enter键时的Tab键按下。为此,我使用了指令:

 private el: ElementRef;
    @Input() onEnter: string;
    constructor(private _el: ElementRef, public renderer: Renderer) {
        this.el = this._el;
    }
    @HostListener('keydown', ['$event']) onKeyDown(e: any) {
        if ((e.which === 13 || e.keyCode === 13)) {
            e.preventDefault();


    const event = new KeyboardEvent("keypress", {
            "key": "Tab"
          });
          this.el.nativeElement.dispatchEvent(event);
............

触发输入键代码,但未发送标签

3 个答案:

答案 0 :(得分:2)

如果要使用ENTER聚焦元素,则可以使用指令

@Directive({
  selector: '[next-tab]',
})
export class NextTabDirective {


  @Input('next-tab') nextControl: any;

  @HostListener("keydown.enter", ["$event"])
  onEnter(event: KeyboardEvent) {
    if (this.nextControl) {
      if (this.nextControl.focus) {
        this.nextControl.focus();
        this.nextControl.select();
        event.preventDefault();
        return false;
      }
    }
  }

  constructor(private control: NgControl) {
  }
}

您可以使用

之类的形式
  <form (submit)="Submit()">
      <input #input0 [next-tab]="input1"  />
      <input #input1 [next-tab]="input2"  />
      <!--the last not have [next-tab]-->
      <!-an ENTER make a submit -->
      <input #input2   />
       <button type="button" (click)="cancel()">Cancel</button>
       <button type="submit">OK</button>
   </form>

我不希望使用这种丑陋的解决方法,但我们可以改善将指令作为下一个标签发送控件数组的指令

@Directive({
  selector: '[next-tab]',
})
export class NextTabDirective {

  @Input('next-tab') nextControl: any[]; //<--an array of controls

  @HostListener("keydown.enter", ["$event"])
  onEnter(event: KeyboardEvent) {

    //find the nextControl not disabled. We check if c is defined
    //This allow us to use *ngIf and not put the control
    let nextControl=this.nextControl.find(c=>c && !c.disabled);
    if (nextControl) {
      if (nextControl.focus) {
        nextControl.focus();
        nextControl.select();
        event.preventDefault();
        return false;
      }
    }
  }

  constructor(private control: NgControl) {
  }
}

表格看起来像

   <form (submit)="Submit()">
      <!--see that we create an array-->
      <input #input0 [next-tab]="[input1,input2,input3]"  />
      <input #input1 [next-tab]="[input2,input3]"  />
      <!--if only one element, we make an array of one element-->
      <input #input2 [style.display]="existInput2?'inherit':'none'" [next-tab]="[input3]"   />
      <!--if we want make invisible control NOT use *nfIf, therefore, we must hidden and disabled too -->

      <input #input3 />
       <button type="button" (click)="cancel()">Cancel</button>
       <button type="submit">OK</button>
   </form>

最后,我在https://stackblitz.com/edit/angular-v8fkkf中放了一个堆叠闪电弹

答案 1 :(得分:1)

还有一种更“合适的方式来执行”下一个选项卡” 这个想法是next-tab指令具有两个变量“ self”和“ next-control”。我们不使用@Input,指令就像

@Directive({
  selector: '[next-tab]',
})
export class NextTabDirective {

  self:any;     
  nextControl:any;  //See that is not a @Input

  @HostListener("keydown.enter", ["$event"])
  onEnter(event: KeyboardEvent) {
    if (this.nextControl) {
      if (this.nextControl.focus) {
        this.nextControl.focus();
        this.nextControl.select();
        event.preventDefault();
        return false;
      }
    }
  }

  constructor(private control: ElementRef) {
    //we store in "self" the native element. This make us easy refered to 
    //html properties of control
    this.self=control.nativeElement;
  }
}

在.html中,该伪指令只是next-tab,不是[next-tab],也不是[next-tab] =“”。考虑到input4太用指令“装饰”了,并且所有输入都具有“ name” html属性

<form [formGroup]="myForm" (submit)="submit(myForm)">
  <p>
    <input type="checkbox" formControlName="ckDisabled"/>Disabled input 2
  </p>
  <p>
    <input type="checkbox" formControlName="ckInvisible"/>Invisible input 3
  </p>
  <p>
    Input 1: <input name="input1" formControlName="input1"
              next-tab/>
  </p>
  <p>
    Input 2: <input name="input2" formControlName="input2" tabindex=""
              [enableControl]="!myForm.controls['ckDisabled'].value" 
              next-tab/>
  </p>
  <p [style.display]="myForm.controls['ckInvisible'].value?'none':'inherit'">
    Input 3: <input name="input3" formControlName="input3"
              [enableControl]="!myForm.controls['ckInvisible'].value"
              next-tab
/>
  </p>
  <p>
    Input 4: <input name="input4"  next-tab formControlName="input4"/>
  </p>
  <p>
  <button>OK</button>
</p>
  </form>

现在是.ts。我们使用ViewChildren获取具有next-tab指令的所有元素。

export class AppComponent implements OnInit,AfterViewInit  {
  //We use a ViewChildren to get all the controls width NextTabDirective
  //We use QueryList<NextTabDirective>. So the elements of "inputs"
  //will have the properties: self and nextControl

  @ViewChildren(NextTabDirective) inputs: QueryList<NextTabDirective>;

  myForm:FormGroup;

  constructor(private fb:FormBuilder){}
  //in ngAfterViewInit we asing to nextControl, the self of the next control
  ngAfterViewInit() {
      const controls=this.inputs.toArray();
      //controls will be [input1,input2,input3,input4]
      for (let i=0;i<controls.length-1;i++)
          controls[i].nextControl=controls[i+1].self;        }
}


  ngOnInit()
  {
   this.myForm=this.fb.group({
    ckDisabled:false,
    ckInvisible:false,
    input1:'',
    input2:'',
    input3:'',
    input4:''

  });
  this.onChanges();
  }
  onChanges()
  {
    this.myForm.valueChanges.subscribe((value)=>{
         if (this.inputs)
         {
           //see how we get the control using self.name
           const input1=this.inputs.find(c=>c.self.name=="input1");
           const input2=this.inputs.find(c=>c.self.name=="input2");
           const input3=this.inputs.find(c=>c.self.name=="input3");
           const input4=this.inputs.find(c=>c.self.name=="input4");

           input1.nextControl=(value.ckDisabled && value.ckInvisible)?input4.self:
                            (value.ckDisabled)?input3.self:input2.self;
           input2.nextControl=(value.ckInvisible)?input4.self:input3.self;
         }

    })

  }
  submit(form:any)
  {
    if (form.valid)
      alert("Fom submitted!!")
  }
}

https://stackblitz.com/edit/angular-dzdxmh中有一个stackBlitz

答案 2 :(得分:0)

非常简单,不需要自定义指令或任何依赖:

为您的输入指定一个“#Name”并使用 (keyup.enter) 本机指令

  <mat-form-field>
    <mat-label>xxxx</mat-label>
    <input matInput [(ngModel)]="xxxx" name="xxxx" #xxxxInput (keyup.enter)="yyyyInput.focus()">
  </mat-form-field>

  <mat-form-field>
    <mat-label>yyyy</mat-label>
    <input matInput [(ngModel)]="yyyy" name="yyyy" #yyyyInput (keyup.enter)="zzzzInput.focus()">
  </mat-form-field>

  <mat-form-field>
    <mat-label>zzzz</mat-label>
    <input matInput [(ngModel)]="zzzz" name="zzzz" #zzzzInput>
  </mat-form-field>