Open Closed

Angular: show errors when user clicks submit with invalid form #870


User avatar
0
paul.harriman created

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>

&lt;abp-button iconClass=&quot;fa fa-save&quot; (click)=&quot;save()&quot;&gt;
  {{ 'AbpUi::Save' | abpLocalization }}
&lt;/abp-button&gt;

</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)
  • User Avatar
    0
    Mehmet created
    Support Team

    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
    }
    
  • User Avatar
    0
    paul.harriman created

    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.

  • User Avatar
    0
    Mehmet created
    Support Team

    Can you share the code?

  • User Avatar
    0
    paul.harriman created

    Which r u looking for? Solution 2?

Made with ❤️ on ABP v9.1.0-rc.1. Updated on January 17, 2025, 14:13