После добавления FormControl в angular, как я могу изменить фокус на новый formcontrol без settimeout?

#javascript #angular #focus

Вопрос:

Эй, я не могу перенастроить недавно созданный элемент управления формой с помощью dom, так как он каждый раз отстает на одну строку, это вызвано синхронизацией и асинхронным поведением, но не могу понять, как преодолеть это отставание.

Я перепробовал все циклы жизненного цикла, но не преуспел. Поскольку мне нужно изменить фокус на динамической строке входных данных, я должен добиться этого в то же время при создании строки входных данных, но она создается визуально, но в сохраненном экземпляре переменной она отстает. это может быть связано с асинхронной функцией, и переменная, которую я сохраняю, инициализируется до ее обновления.

Это мои кодовые блоки

     onAddTaka() {
    let takaNum: string = '';
    let indx = (<FormArray>this.productionForm.get('takas')).length - 1;
    if (indx >= 0) {
      let formGrp = (<FormArray>this.productionForm.get('takas')).at(indx);
      let lastTakaNumber = formGrp.value.takaNumber.split(this.serialPrefix)[1];

      takaNum = this.serialPrefix   (parseInt(lastTakaNumber)   1);
    } else {
      takaNum = this.serialPrefix   this.serialStart;
    }

    (<FormArray>this.productionForm.get('takas')).push(
      new FormGroup({
        'takaNumber': new FormControl(takaNum, Validators.required),
        'weight': new FormControl(null, [Validators.required, Validators.min(0)]),
        'length': new FormControl(null, [Validators.required, Validators.min(0)])
      })
    );
    this.onTakaNumberChange({target : { value: takaNum}},indx   1);
  }

kd(ele, plc) {
    if(ele.keyCode == 13) {
      ele.preventDefault();
      if(ele.ctrlKey == true) {
        document.getElementById("save_btn").focus();
      }
      switch(plc){
        case 0 : ele.path[2].children[1].children[0].focus();
                break;
        case 1 : ele.path[2].children[2].children[0].focus();
                break;
        case 2 :
                this.onAddTaka();
                setTimeout(() => {
                  this.updateEle();
                  this.setFocus();
                }, 1);
                break;
        default:
          this.alertMessage = "Some thing went Wrong in key Press detection Contact support!";
      }
      
    }
  }


  updateEle(){
    this.le = <HTMLElement>document.body.children[0].children[2].children[0].children[1].children[1].children[1].lastElementChild;
    if(this.le) {
      this.le = (<HTMLElement>this.le.children[0].children[0]);
    }
  }

  setFocus() {
    this.le.focus();
  }

  onTakaNumberChange(event: any, index: number) {
    let inputTakaNumber = event.target.value;
    
    this.takaNumberVerified = this.takaService.isUniqueTakaNumber(inputTakaNumber);

    if (!this.takaNumberVerified) {
      this.alertMessage = `The Taka Number (${inputTakaNumber}) is already used Try another One in row ${index   1}`;
    }

    let str;
    if (this.takaNumberVerified) {
      str = 'form-control is-valid';
    } else {
      str = 'form-control is-invalid';
    }

    this.avgWt.forEach((item, i) => {
      if (index === i) {
        item.nativeElement.children[0].children[0].className = str;
      }
    });

  }

get controls() {
    return (<FormArray>this.productionForm.get('takas')).controls;
  }
 

Это тогда html

 <section class="container" *ngIf="voucherGenerated">
    <br>
    <table class="table table-striped table-hover text-center">
      <thead>
        <tr>
          <th scope="col">Taka No.</th>
          <th scope="col">Length (in mtr.)</th>
          <th scope="col">Weight</th>
          <th scope="col">Avg. Weight</th>
        </tr>
      </thead>
      <tbody formArrayName="takas">
        <tr *ngFor="let takaCtrl of controls; let i = index;" [formGroupName]="i" #avgWt>
          <th scope="row">
            <input type="text" name="takaNumber" id="takaNumber" class="form-control" placeholder="W00001" formControlName="takaNumber" (keydown)="kd($event,0)" (focusout)="onTakaNumberChange($event,i)">
          </th>
          <td>
            <input type="number" name="length" id="takaLength" class="form-control" placeholder="Length" formControlName="length" (keydown)="kd($event,1)" (input)="onChange($event,1,i)">
          </td>
          <td>
            <input type="number" name="Weight" id="takaWeight" class="form-control" placeholder="Weight" formControlName="weight" (keydown)="kd($event,2)" (input)="onChange($event,0,i)">
          </td>
          <td>
            <span class="form-control">0</span>
          </td>
          <td>
            <button type="button" class="btn btn-danger" (click)="onRemoveTaka(i)">X</button>
          </td>
        </tr>
      </tbody>
    </table>
    <hr>
    <div class="row mb-2 mt-2">
      <div class="col">
        <button type="button" class="btn btn-outline-dark" (click)="onAddTaka()">Add Taka</button>
      </div>
      <div class="col text-end">
        <button id="save_btn" class="btn btn-primary" type="submit" [disabled]="!productionForm.valid">Save Production</button>
      </div>
    </div>
  </section>
 

Комментарии:

1. Я знаю, что вы не хотите этого делать, но на самом деле проще всего сделать это rxjs debouncetimer

Ответ №1:

Вы можете использовать ссылку на шаблон и просмотреть детей,

 <!--use #input in the "input" you want to make the focus-->
<-- NOT in the others, e.g. you want to focus in "takaNumber"
<input #input type="text" name="takaNumber"..>
 

Представление, которое используют {read:ElementRef} дети, потому что вам нужен «html-тег», а не элемент управления формой

 @ViewChildren('input',{read:ElementRef}) inputs:QueryList<ElementRef>

    
 

Тогда у вас есть два варианта:

1.-когда вы добавляете новую группу форм в массив, сделайте вдох(*) в Угловой и сфокусируйте последний элемент списка запросов

 onAddTaka() {
    ....
    setTimeout(()=>{
        //if you want to focus the nth-index
        //use inputs.find((_,i)=>i==index).nativeElement.focus()
        //if you want the nth
        inputs.last.nativeElement.focus()
    })
  }
 

(*)вам нужно подождать, чтобы перерисовать формат изображения перед фокусировкой, поэтому вы используете setInterval с «0 миллисекундами».

2.- Подпишитесь на inputs.valueChange в ngAfterViewInit-Изменение значения при добавлении/удалении одного элемента «Списка запросов»

   ngAfterViewInit()
  {
     this.inputs.changes.subscribe(res=>{
       if (res.length)
        res.last.nativeElement.focus()
     })
  }