Okay, to solve this problem I used a combination of lightning-record-edit-form and lightning-record-view-form and I just omitted the lightning-messages tag. I used a js variable called "editMode" to conditionally render lightning-input-field vs lightning-output-field. Then, I use handleError() onerror to parse the error message and display a closable error toast to the user.
<template>
<lightning-record-edit-form record-id={recordId} object-api-name="Opportunity" onerror={handleError}>
<lightning-record-view-form record-id={recordId} object-api-name="Opportunity">
<div class="slds-box">
<lightning-card title="Opportunity Overview">
<template if:true={editMode}>
<lightning-button variant="Neutral" label="Save" title="Save" type="submit"
icon-name="utility:save" slot="actions" class="slds-p-around_xxx-small"></lightning-button>
<lightning-button variant="brand" label="Cancel" title="Cancel" type="reset"
onclick={clearEditMode} icon-name="utility:undo" slot="actions"
class="slds-p-around_xxx-small"></lightning-button>
</template>
<template if:false={editMode}>
<lightning-button variant="brand" label="Edit" title="Edit" onclick={setEditMode}
icon-name="utility:edit" slot="actions" class="slds-p-around_xxx-small"></lightning-button>
</template>
<lightning-layout multiple-rows="true">
<lightning-layout-item size="6" padding="around-small">
<template if:true={editMode}>
<lightning-input-field field-name="name"></lightning-input-field>
</template>
<template if:false={editMode}>
<lightning-output-field field-name="name"></lightning-output-field>
</template>
</lightning-layout-item>
<!-- ... repeat above for all fields... -->
</lightning-layout>
</lightning-card>
</div>
</lightning-record-view-form>
</lightning-record-edit-form>
Here is js controller:
@track editMode;
connectedCallback() {
this.editMode = false;
}
setEditMode(){
this.editMode = true;
}
clearEditMode(){
this.editMode = false;
}
handleError(event) {
let message = event.detail.detail;
//do some stuff with message to make it more readable
message = "Something went wrong!";
this.showToast(TOAST_TITLE_ERROR, message, TOAST_VARIANT_ERROR);
this.clearEditMode();
}
showToast(theTitle, theMessage, theVariant) {
const event = new ShowToastEvent({
title: theTitle,
message: theMessage,
variant: theVariant
});
this.dispatchEvent(event);
}