0

I have a LWC component that displays a datatable showing the related Contacts when a particular record from an Account object is selected from a combobox. A button is also displayed, which when clicked invokes a modal window that allows to add record to Contact object of the selected Account. My requirement is that after the record is inserted through the modal window the list in the datatable should also be refreshed. I am unable to use @wire decorator properly here. Any help is appreciated. The code is posted below:

accountContactsdatatable.html

<template>
    <lightning-card title="Select Account">
        <!--Combobox to select Account-->
        <lightning-combobox label="Accounts"
                            value={value}
                            placeholder = "Select an Account"
                            options={options}
                            onchange={handleChangedValue}
        ></lightning-combobox>                        
    </lightning-card>

    <template if:true={addButton}>
        <div class='slds-card'>
            <!--Add contact button-->
            <lightning-button label='Add Contact'
                              titlle='Add Contact'
                              onclick={addContact}>
            </lightning-button>
        </div>
    </template>
           
    <!-- Modal window -->        
    <template if:true={modalWindow}>
        <section role="dialog" tabindex="-1" aria-labelledby="modal-heading-01" aria-modal="true" aria-describedby="modal-content-id-1" class="slds-modal slds-fade-in-open">
            <div class="slds-modal__container">
                <header class="slds-modal__header">
                    <button class="slds-button slds-button_icon slds-modal__close slds-button_icon-inverse" title="Close" onclick={customHideModalPopup}>
                        <lightning-icon icon-name="utility:close"
                                        alternative-text="close"
                                        variant="inverse"
                                        size="small" >
                        </lightning-icon>
                        <span class="slds-assistive-text">Close</span>
                    </button>
                    <h2 class="slds-text-heading_medium slds-hyphenate">Enter Contact Details</h2>
                </header>
                <div class="slds-modal__content slds-p-around_medium">
                    <div class="slds-grid slds-wrap">
                        <div class="slds-col slds-size_6-of-12 slds-p-horizontal--medium slds-m-bottom_medium">
                            <lightning-input label="First Name" value={rec.FisrtName} onchange={fnameChange}></lightning-input>
                        </div>
                        <div class="slds-col slds-size_6-of-12 slds-p-horizontal--medium slds-m-bottom_medium">
                            <lightning-input label="Last Name" value={rec.LastName} onchange={lnameChange}></lightning-input>
                        </div>
                        <div class="slds-col slds-size_6-of-12 slds-p-horizontal--medium slds-m-bottom_medium">
                            <lightning-input label="Email" value={rec.Email} onchange={emailChange}></lightning-input>
                        </div>
                        <div class="slds-col slds-size_6-of-12 slds-p-horizontal--medium slds-m-bottom_medium">
                            <lightning-input label="Mobile" value={rec.Mobile} onchange={mobileChange}></lightning-input>
                        </div>
                        <footer class="slds-modal__footer">
                            <button class="slds-button slds-button--destructive" onclick={customHideModalPopup}>Cancel</button>
                            <button class="slds-button slds-button_brand" onclick={createContact}>Create Contact</button>
                        </footer>
                    </div>
                </div>
            </div>
        </section>
        <div class="slds-backdrop slds-backdrop_open">
        </div>
    </template>
    <!--Datatable-->
    <template if:true={dataTable}>
        <lightning-card title="Contacts">
            <div style="height: 200px">
                <lightning-datatable key-field="id"
                                     data={data}
                                     columns={columns}>
                </lightning-datatable>
            </div>
        </lightning-card>
    </template> 
</template>

accountContactsdatatable.js

import { LightningElement, track, wire } from 'lwc';
import CONTACT_OBJECT from '@salesforce/schema/Contact';
import FNAME_FIELD from '@salesforce/schema/Contact.FirstName';
import LNAME_FIELD from '@salesforce/schema/Contact.LastName';
import EMAIL_FIELD from '@salesforce/schema/Contact.Email';
import MOBILE_FIELD from '@salesforce/schema/Contact.MobilePhone';
import ACID_FIELD from '@salesforce/schema/Contact.AccountId';
import getAccounts from '@salesforce/apex/accountsContactdatatableController.getAccounts';
import getContacts from '@salesforce/apex/accountsContactdatatableController.getContacts';
import insertContact from '@salesforce/apex/accountsContactdatatableController.insertContact';
import { refreshApex } from '@salesforce/apex';
import { ShowToastEvent } from 'lightning/platformShowToastEvent';

const columns = [
    {label : 'Contact Name', fieldName : 'Name'}
]

export default class AccountContactsdatatable extends LightningElement {

    @track value = '';
    refreshTable;
    @track optionList = [];
    @track data = [];
    @track columns = columns;
    @track modalWindow = false;
    @track dataTable = false;
    @track addButton = false;
    @track fname = FNAME_FIELD;
    @track lname = LNAME_FIELD;
    @track email = EMAIL_FIELD;
    @track mobile = MOBILE_FIELD;
    @track actid = ACID_FIELD;
    rec = {
        FirstName : this.fname,
        LastName : this.lname,
        Email : this.email,
        Mobile : this.mobile,
        AccountId : this.value
    }

    get options(){
        return this.optionList;
    }

    connectedCallback(){
        getAccounts()
        .then(response=>{
            let arr = [];
            for(var i=0; i<response.length; i++){
                arr.push({label : response[i].Name, value : response[i].Id});
            }
            this.optionList = arr;
        })   
    }

    handleChangedValue(event){
        this.value = event.detail.value;
        this.addButton = true;
        this.dataTable = true;

        getContacts({AcctId : this.value})
        .then(result=>{
            this.data = result;
            this.refreshTable = result;
        })
        .catch(error =>{
            window.alert("Error:"+error)
        })
    }

    addContact(){
        this.modalWindow = true;
    }

    customHideModalPopup(){
        this.modalWindow = false;
    }

    createContact(event){
        this.rec.AccountId = this.value;
        insertContact({ cnt : this.rec })
        .then(result => {
            this.message = result;
            this.error = undefined;
            if(this.message !== undefined) {
                this.rec.FirstName = '';
                this.rec.LastName = '';
                this.rec.Email = '';
                this.rec.Mobile = '';
                this.dispatchEvent(
                    new ShowToastEvent({
                        title: 'Success',
                        message: 'Contact created Succesfully',
                        variant: 'success',
                    }),
                );
            }
        })
        .catch(error => {
            this.message = undefined;
            this.error = error;
            this.dispatchEvent(
                new ShowToastEvent({
                    title: 'Failed to create contact',
                    message: error.body.message,
                    variant: 'error',
                }),
            );
        });

        this.customHideModalPopup();
    }

    fnameChange(event){
        this.rec.FirstName = event.target.value;
    }

    lnameChange(event){
        this.rec.LastName = event.target.value;
    }

    emailChange(event){
        this.rec.Email = event.target.value;
    }

    mobileChange(event){
        this.rec.Mobile = event.target.value;
    }
}

accountsContactdatatableController.cls

public with sharing class accountsContactdatatableController {
    //Method to return list o Accounts to LWC
    @AuraEnabled
    public static List<Account> getAccounts(){
        try {
            List<Account> accountList = [SELECT Id, Name FROM Account];
            return accountList;
        } catch (Exception e) {
            throw new AuraHandledException(e.getMessage());
        }
    }

    //Method to return related contacts to LWC
    @AuraEnabled
    public static List<Contact> getContacts(String AcctId){
        try {
                List<Contact> cntcList = [SELECT Id,Name,AccountId FROM Contact WHERE AccountId =: AcctId];
                return cntcList;
            } catch (Exception e) {
                throw new AuraHandledException(e.getMessage());
            }
    }

    //Method to insert record in Contact object
    @AuraEnabled
    public static Contact insertContact(Contact cnt){
        try {
                insert cnt;
                return cnt;
        } catch (Exception e) {
            throw new AuraHandledException(e.getMessage());
        }
    }
}

TIA.

1 Answer 1

0

Any special reason you need apex code for this? Look into (relatively new) https://developer.salesforce.com/docs/component-library/bundle/lightning-ui-related-list-api/documentation, maybe you can pull it all off with pure LWC.

To refresh a datatable... eh.

The so-so way you could try explicitly calling

getContacts({AcctId : this.value})
        .then(result=>{
            this.data = result;
            this.refreshTable = result;
        })
        .catch(error =>{
            window.alert("Error:"+error)
        })

inside your contact insert success. It should work because you didn't mark the Apex method as cacheable.

The better way - yes, the apex method should be @AuraEnabled(cacheable=true) for better performance. And then the trick will not work because SF will see same account id passed and will decide there's nothing to do. There's a refreshApex call in JS that will force lwc to call the method again and get fresh data.

Or you could just add the inserted contact to the list in JS, I mean you're returning it from apex to JS...

Or ditch the whole thing and check that related records API.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.