Angular 关注ngselect on empty using指令

Angular 关注ngselect on empty using指令,angular,Angular,我有一个模板驱动的表单。表单中有一个ng select下拉列表的必填字段和一个文本框。当我按submit method时 如果ng select下拉列表为空,则焦点应转到ng select 下拉列表 如果选择了ng select,则如果文本框为空 然后焦点应该转到文本框。 这是我用指令实现的。我实现了第二个指令(选择ng select,然后如果文本框为空,则焦点应转到文本框)。但我不能达到第一个条件 我在下面添加了一个示例stackblitz链接供您参考。在此重点介绍select。我需要使用ng

我有一个模板驱动的表单。表单中有一个ng select下拉列表的必填字段和一个文本框。当我按submit method时

  • 如果ng select下拉列表为空,则焦点应转到ng select 下拉列表
  • 如果选择了ng select,则如果文本框为空 然后焦点应该转到文本框。 这是我用指令实现的。我实现了第二个指令(选择ng select,然后如果文本框为空,则焦点应转到文本框)。但我不能达到第一个条件
  • 我在下面添加了一个示例stackblitz链接供您参考。在此重点介绍select。我需要使用ng select实现同样的功能。

    指令

     @HostListener('submit')
      onFormSubmit() {
        let invalidControl = this.el.nativeElement.querySelector('.ng-invalid');
        if (invalidControl) {
          invalidControl.focus();
        }
      }
    

    ng invalid类将应用于ng select,因此此.el.nativeElement.querySelector(“.ng invalid”)将返回ng select标记,并且它没有focus方法,这就是解决方案无法工作的原因

    解决方案:

    在FocusOneErrorDirective中使用ContentChild获取NgSelectComponent实例。然后我们可以对其调用focus方法,如下所示:

    @Directive({
      selector: "[appFocusonerror]"
    })
    export class FocusonerrorDirective {
      @ContentChild(NgSelectComponent) select: NgSelectComponent;
    
      constructor(private el: ElementRef) {}
    
      @HostListener("submit")
      onFormSubmit() {
        const invalidControl = this.el.nativeElement.querySelector(".ng-invalid");
        if (invalidControl) {
          if (invalidControl.tagName === "NG-SELECT") {
            this.select.focus();
            return;
          }
          invalidControl.focus();
        }
      }
    }
    

    您需要检查“无效”是否包含内容输入

      @HostListener("submit")
      onFormSubmit() {
        const invalidControl = this.el.nativeElement.querySelector(".ng-invalid");
    
        if (invalidControl) {
          //search if is a "complex input"
          const input = invalidControl.querySelector("input");
          if (input) 
            input.focus();
          else {
            invalidControl.focus();
          }
        }
      }
    
    注意:我不太喜欢对ng invalid使用querySelector,所以为了解决这个问题,我希望有一个指令

    @Directive({
      selector: "[ngModel],[formControl]"
    })
    export class NativeElementDirective {
      public el:any
      constructor(elementRef: ElementRef, @Optional() public control: NgControl, @Optional() select:NgSelectComponent) {
        if (select)
          this.el=select
        else
          this.el=elementRef.nativeElement
    
      }
    }
    
    更新改进指令

    @Directive({
      selector: "[ngModel],[formControl]"
    })
    export class NativeElementDirective {
      public el:any
      constructor(elementRef: ElementRef, @Optional() public control: NgControl, @Optional() select:NgSelectComponent) {
        if (select)
          this.el=select
        else
          this.el=elementRef.nativeElement
    
      }
    }
    
    此指令获取所有ngModel或FormControls。如果ng select存储在“el”中是自己的ng select,则存储elementRef.nativeElement

    因此,我们的focusonerror指令变成

    export class FocusonerrorDirective {
      constructor() {}
    
      @ContentChildren(NativeElementDirective) controls: QueryList<NativeElementDirective>;
      @HostListener("submit")
      onFormSubmit() {
        const control = this.controls.find(x => x.control.invalid);
        if (control)
          control.el.focus()
      }
    }
    
    导出类FocusonerrorDirective{
    构造函数(){}
    @ContentChildren(NativeElementDirective)控件:QueryList;
    @HostListener(“提交”)
    onFormSubmit(){
    const control=this.controls.find(x=>x.control.invalid);
    如果(控制)
    control.el.focus()
    }
    }
    

    你能创建stackblitz吗?我添加了一个stackblitz链接。这同样需要通过删除select来实现。必须使用ng select,而不是ng select。当你按submit时,它会自动聚焦ng selectHi chellappan。你说你可以使用组件实例解决此错误。你能告诉我如何实现吗?什么错误你收到了吗?谢谢你的回答。它起作用了。你能解释一下代码吗?恐怕代码不起作用,你只问第一个ng select-你正在使用
    @ContentChild(NgSelectComponent)select:NgSelectComponent并且这只获得第一个ng select。如果您有两个ng select,无效的是最后一个,则代码不起作用。根据问题是,他只使用了一个ng select,如果他想执行多个ng select,他可以使用contentChildren来获取所有ng-select@mohammedfahimullah由于我们在父窗体上放置了AppFocusOneError指令,所有属于表单元素的输入都是AppFocusOneError指令的内容子元素。我们可以使用contentchild查询contentchild元素或组件实例。没问题,我很快就读到了这个问题,并问我多个ng select会发生什么。注意:我喜欢你提出的询问“标记名”的想法,因为某些原因,我试图实现你的代码。Idk不起作用。检查你的stackblitz它对你起作用,但对我不起作用。如果你使用“指令选项”请记住,在模块的
    声明中包含指令我完成了stackblitz和工作:-只需将文件
    focusonerror.directive.ts
    替换为我的文件,并在app.module.ts声明中添加指令
    NativeElementDirective
    。如果在您的真实应用程序中,您的组件属于,例如,
    另一个.module.ts
    请记住,指令必须属于此模块-或者如果您有一个util.module.ts,请在其中声明该指令(此模块由另一个.module.ts导入
    当我处理此模块时,您需要将指令导出到。控制FocusOneError指令中存在的值我得到了此指令,但当我处理您的数据时,它不同,我缺少什么。更改:EventEmitter{u isScalar:false,Observators:Array(0),closed:false,isStopped:false,hasError:false,…}dirty:false first:undefined last:undefined length:0_results:[]检查ng select上的版本和angular的版本。如果使用angular 8的版本,则需要ng select v3.0
    npm安装--save@ng select/ng-select@3.0.0
    -或在addDependencies中的stackblitz:
    @ng选择/ng-select@3.0.0
    ,请参阅文档:。注意:对不起,我在评论中添加的stackblitz链接错误,刚刚更正