Check the docs before asking a question: https://docs.abp.io/en/commercial/latest/ Check the samples, to see the basic tasks: https://docs.abp.io/en/commercial/latest/samples/index The exact solution to your question may have been answered before, please use the search on the homepage.
- ABP Framework version: v4.0.2
- UI type: Angular
- DB provider: EF Core
- Tiered (MVC) or Identity Server Seperated (Angular): yes / no
- Exception message and stack trace:
- Steps to reproduce the issue:
Have a form in a modal with validation. For simplicity mark fields as required
component.html <abp-modal [(visible)]="isModalVisible" [busy]="modalBusy" (disappear)="form = null"> <ng-template #abpHeader> <h3>{{ (selected?.id ? 'AbpUi::Edit' : 'HR::NewEmployeeExperience') | abpLocalization }}</h3> </ng-template>
<ng-template #abpBody> <form [formGroup]="form" validateOnSubmit> <div class="mt-2 fade-in-top"> <div class="form-group"> <label for="employeeExperience-workplace"> {{ 'HR::Workplace' | abpLocalization }} </label> <span class="req-mark"> * </span> <input type="text" id="employeeExperience-workplace" class="form-control" formControlName="workplace" /> </div> <div class="form-group"> <label for="employeeExperience-seniority"> {{ 'HR::Seniority' | abpLocalization }} </label> <span class="req-mark"> * </span> <input type="number" id="employeeExperience-seniority" class="form-control" formControlName="seniority" /> </div> <div class="form-group"> <label for="employeeExperience-position"> {{ 'HR::Position' | abpLocalization }} </label> <span class="req-mark"> * </span> <input type="text" id="employeeExperience-position" class="form-control" formControlName="position" /> </div> </div> </form> </ng-template>
<ng-template #abpFooter> <button type="button" class="btn btn-secondary" #abpClose> {{ 'AbpUi::Cancel' | abpLocalization }} </button>
<abp-button iconClass="fa fa-save" (click)="save()">
{{ 'AbpUi::Save' | abpLocalization }}
</abp-button>
</ng-template> </abp-modal>
component.ts buildForm() { this.form = this.fb.group({ employeeCode: [this.employeeCode || '', [Validators.required]], workplace: [this.selected.workplace || '', [Validators.required]], seniority: [this.selected.seniority || '', [Validators.required]], position: [this.selected.position || '', [Validators.required]], }); }
submitForm(): void { if (this.form.invalid) { return; } .... remaining logic to do update }
don't enter any data, click save. the click will send it to the component, and indeed the form is invalid. the form is not marked up b/c validateOnSubmit is not triggered, the user cannot visually see what the issue is. i tried to move the form html element after <abp-modal [(visible)]="isModalVisible" [busy]="modalBusy" (disappear)="form = null"> so it would wrap all the ng-template. I also removed the click event and replaced it with a buttonType="submit" the html form element is not rendered.
4 Answer(s)
-
0
Hi
validateOnSubmit
is not work in your case. Because submit button and form are placed in different templates. You can use the methods below to achieve this:Recommended:
<abp-modal [(visible)]="isModalVisible"> <ng-template #abpHeader> <h3>Modal Title</h3> </ng-template> <ng-template #abpBody> <form [formGroup]="form" (ngSubmit)="save()" validateOnSubmit> <!-- form elements here --> <div class="text-right mt-2"> <button type="button" class="btn btn-secondary mr-1" #abpClose> Close </button> <!-- make sure the button type is submit and placed between the <form> tag --> <abp-button iconClass="fa fa-check" (click)="save()" buttonType="submit"> Save </abp-button> </div> </form> </ng-template> </abp-modal>
Alternate:
<!-- HTML template --> <abp-modal [(visible)]="isModalVisible"> <ng-template #abpHeader> <h3>Modal Title</h3> </ng-template> <ng-template #abpBody> <!-- set a hash id as shown below (#myForm) --> <form #myForm [formGroup]="form" (ngSubmit)="save()" validateOnSubmit> <!-- form elements --> </form> </ng-template> <ng-template #abpFooter> <abp-button iconClass="fa fa-check" (click)="save()"> Save </abp-button> </ng-template> </abp-modal> ---------------- // ts // catch the form element via ViewChild @ViewChild('myForm', { static: false, read: ElementRef }) myFormRef: ElementRef<HTMLFormElement>; save() { if (this.form.invalid) { // dispatch submit event of form element this.myFormRef.nativeElement.dispatchEvent(new Event('submit', { bubbles: true, cancelable: true })); return; } // your save logic }
-
0
I', going with the first solution. I have to do some ui repair as moving the footer creates some visual issues. the send solution did not work for me.
-
0
Can you share the code?
-
0
Which r u looking for? Solution 2?