У меня есть Реактивная форма (#myform
) с кнопкой "foo"
, к которой прикреплена (click) = myform.submit()
, так что форма будет отправляться только при нажатии этой кнопки, а не при событиях Enter
. Компонент прослушивает Enter
события и отправляет blur
в этом случае, и все FormControls имеют {updateOn: 'blur'}
, поэтому blur
события запускают обновления (т. Е. valueChanges
и т. Д.).
Myпроблема заключается в следующем: если я ввожу данные в Input
(или выбираю элемент в Select
), не нажимая Enter
или Tabbing
из элемента, а затем нажимаю "foo"
, то есть "Submit"
Похоже, что нажатие кнопки "foo"
вызывает только событие blur
без запуска отправки формы (через myform.submit
). То есть, submit
«проглатывается» событием blur
.
Как я могу настроить это так, чтобы, если я не Enter
или Tab
вне элемента, и немедленнонажмите "foo"
, элемент будет обновлен с помощью события blur
И ТОЛЬКО форма будет также отправлена?
Я пробовал такие вещи, как: 1. сначала обработать blur
, а затем попробоватьпрограммный вызов myform.submit()
в компоненте (путем доступа от Form
до @ViewChild
) и 2. добавление прослушивателя (blur)= (submitNow && setTimeout(()=>myform.submit(),50)
в представлении шаблона. На данный момент у меня даже нет этого setTimeout
вызова для компиляции, и ни один из подходов, которые я пробовал, кажется, пока не работает.
Исходный код (упрощенный) выглядит так: шаблон details.component.html
<form #myform [formGroup]="form" method="POST" action="http://localhost:3000/users/{{userID}}/details">
<ng-container *ngFor="let sec of datArr">
<ng-container *ngFor="let row of sec; let i = index">
<input type="text"
[appTag]="row[datColEnum.tabCol]"
(keydown.enter)="onEnter($event)"
tabindex = "{{row[datColEnum.tabCol]}}"
name="{{row[datColEnum.controlNameCol]}}" value="{{row[datColEnum.valueCol]}}"
formControlName="{{row[datColEnum.controlNameCol]}}"/>
</ng-container>
</ng-container>
<button name="foo" type="button" (click)="myform.submit()">Submit</button>
</form>
компонент details.component.ts
export class DetailsComponent implements OnInit, AfterViewInit {
@ViewChildren(TagDirective) ipt!: QueryList<ElementRef>;
@ViewChild('myform', {static: true}) myform: any;
data: Object;
meta: Object;
datArr: any[] = [];
formCtls: any = {};
form: FormGroup = new FormGroup({});
tabIdx: number = 0;
focusItm: number = 0;
submitNow: boolean = false;
constructor(private member: MemberService, private route: ActivatedRoute, private el: ElementRef) { }
ngAfterViewInit() {
this.ipt.changes.subscribe(list=>{
setTimeout(()=>
list.filter(itm=>+itm.id===this.focusItm%this.tabIdx).forEach(itm=>{
if (!this.first_pass) this.navigateTo(itm.id);
}
),100)
})
}
doSubmit() {
this.submitNow = true;
}
navigateTo(ti: number) {
console.log(`NAVIGATING TO ITEM WITH TAB INDEX: ${ti}`)
this.ipt["_results"][ti-1].el.nativeElement.focus();
this.ipt["_results"][ti-1].el.nativeElement.style.borderWidth = "3px";
}
onEnter(e: Event) {
let cname = (<HTMLInputElement | HTMLSelectElement>e.target).name;
let idx = 0;
for (let itm of this.ipt["_results"]) {
if (itm.el.nativeElement.name === cname) {
this.focusItm = (itm.id+1)%this.ipt["_results"].length;
itm.el.nativeElement.style.borderWidth = "1px";
break;
}
}
e.target.dispatchEvent(new Event('blur'));
}
ngOnInit() {
. . .
. . .
//SET EVERYTHING UP
this.renderDataArray();
. . .
. . .
})
};
// SET UP ALL THE FormControls, etc. AND THE DATA MODEL datArr USED TO RENDER THE TEMPLATE
renderDataArray() {
this.datArr = [];
this.tabIdx = 0;
Object.keys(this.meta).forEach((sec,idx) => {
let rowCnt = this.getActiveArrayLen(sec);
for (let i = 0; i < rowCnt; i++) {
Object.keys(this.data[sec]).
.map((fld,idx)=>{
let itm = this.data[sec][fld];
this.tabIdx += 1;
let val = getVal();
let ctlName = sec+this.FLD_SPLIT_CHAR+fld;
this.removeControl(ctlName);
this.formCtls[ctlName] = new FormControl(val, {updateOn: 'blur'});
this.form.addControl(ctlName, this.formCtls[ctlName]);
of(this.tabIdx).
pipe(switchMap(ti=>this.formCtls[ctlName].valueChanges.
pipe(map(newVal => [newVal,ti]))
)
).subscribe(([newVal,ti])=>{
if (Array.isArray(itm["value"])) {
itm["value"][+(itm["value"].length || 1)-1]=newVal || '';
} else {
itm["value"]=newVal || '';
}
this.focusItm = (ti+1)%this.ipt["_results"].length;
this.renderDataArray();
});
. . .
. . .