[SalesForce] lightning-input-field reportValidity and stop execution

I have an lwc form that consists of a lightning-record-edit-form and some lightning-input-fields

I have to override the submit button with apex as I have to perform some custom logic.

There are some validation rules defined against the lightning-input-field which I am trying to fire using reportValidity() which fires correctly. But after the rule fires, I want to stop execution. This is not happening and the code is still going to apex. How can I stop execution if reportValidity() throws up errors on lightning-input-field?

Here is the code
HTML

<lightning-record-edit-form object-api-name={objName} onsubmit={handleSubmit} onsuccess={handleSuccess} record-id={recordId}>

    <lightning-input-field field-name={fieldName} name = {fieldName}  onchange={handleChange}></lightning-input-field>

     <lightning-button variant="brand" type="submit" name="save" label="Submit" onclick={validateFields}>
     </lightning-button>

</lightning-record-edit-form>

JS:

validateFields(event) {
    this.template.querySelectorAll('lightning-input-field').forEach(element => {
                element.reportValidity();
            });

    //check if there is an error. not sure how to check if reportValidity throws an error as the code proceeds to execute apex even when there is an error
        
     let isError = this.template.querySelector(".slds-has-error");
    
    //if no error then only call apex from handleSubmit
     if(!isError) {
            this.template.querySelector("lightning-record-edit-form").submit();
        }
    }

Best Answer

EDIT 2: You can't call validation rules separately from DML operations: Fire Validation Rule from Apex

Please see Trigger Order of Execution: https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_triggers_order_of_execution.htm

If you are attempting to use lightning-record-edit-form as a form to collect valid input without saving to the DB, and then handle it via another Apex class, then you can't do that: https://developer.salesforce.com/docs/component-library/documentation/en/lwc/lwc.data_salesforce_write. Instead, create a custom lookup component, use input fields, handle all the logic client side, and then pass the input to your class, otherwise lightning-record-edit-form must save to the database to run "reportValidity" and return Validation Rule errors.


Please see the section "Overriding Default Behaviours": https://developer.salesforce.com/docs/component-library/bundle/lightning-record-edit-form/documentation

You'll want to use event.preventDefault() in your custom event handlers and then after all validation succeeds, call the .submit() or custom Apex

EDIT: My mistake, you can't set custom error messages on input-field like you can with input setCustomValidity() see: Lightning Web Component Custom Errors

But, you can handle the errors in a separate component / UI feature -- here I add errors to an array.

customErrors = [];

handleSubmit(event) {
    event.preventDefault();
    this.customErrors = [];
    let isValid = [...this.template.querySelectorAll('lightning-input-field')].reduce( (val, inp) => {
        let inpVal = true;
        // Custom Logic
        switch (inp.fieldName) {
            case 'Name':
                inpVal = inp.value == 'Logic' ? true : false;
                if (!inpVal) { this.customErrors.push('Custom Error'); }
                break;
            default:
                inpVal = true;
                break;
        }
        return val && inpVal;
    }, true);

    if (isValid) {
        this.template.querySelector('lightning-record-edit-form').submit();
        // Validation Rules will run and return errors after the submit / DML operation
    }
}