Displaying the Picklist field as Check box in record Edit & New form

In this post , we will see two things.
  • How to display the Picklist value as radio check box in record edit form using js controller
  • After saving the record , how to bind the value again, once user edit the record
Here are component structure for this requirement.

Aura Component :
  •       pickListToChkBoxAura - Purpose of the component is to override the standard edit and new  button ,since LWC is not supported for button overriding
Lightning Web component :
  •      pickListToChkBoxForm 

pickListToChkBoxAura.cmp

<aura:component implements="lightning:actionOverride,force:appHostable,flexipage:availableForAllPageTypes,
force:hasRecordId" access="global">
<c:pickListToChkBoxForm recordId="{!v.recordId}"></c:pickListToChkBoxForm>
</aura:component>



pickListToChkBoxForm.html 

we can use lightning-input with type equals radio to display the pick-list as Radio checkbox . 

<template>
<lightning-record-edit-form class="Case" object-api-name="Case" record-id={recordId} onsuccess={handleSucess} onsubmit={handleSubmit}>

<lightning-input-field field-name="Subject">
</lightning-input-field>

<lightning-input-field field-name="Description">
</lightning-input-field>
<!--Display the picklist value as radio button-->
<template for:each={originValues} for:item="item">
<lightning-input name="Origin" checked={item.checkedBoolean} placeholder="Account Type" key={item.value}
label={item.label} data-value={item.value} type="radio" onselect={handleChange}></lightning-input>
</template>

<lightning-button type="submit" class="slds-m-top_small" label="Save">
</lightning-button>

</lightning-record-edit-form>

</template>



pickListToChkBoxForm.js 

We will make use of the inbuilt uiObjectInfoApi library provided by salesforce to get the picklist values.  

import { LightningElement, api, track, wire } from 'lwc';
import { NavigationMixin } from 'lightning/navigation';
import { getRecord, getFieldValue } from 'lightning/uiRecordApi';
import { ShowToastEvent } from 'lightning/platformShowToastEvent';
import { getPicklistValues } from 'lightning/uiObjectInfoApi';
import { getObjectInfo } from 'lightning/uiObjectInfoApi';
import CASE_OBJECT from '@salesforce/schema/Contact';
import ORIGINFIELD from '@salesforce/schema/Case.Origin';


export default class PickListToChkBoxForm extends NavigationMixin(LightningElement) {
@api recordId;
@track fields = {};
@track originValues;
@track value;


@wire(getObjectInfo, { objectApiName: CASE_OBJECT })
objectInfo;

/*wire method to get the origin picklist values */
@wire(getPicklistValues, { recordTypeId: '$objectInfo.data.defaultRecordTypeId', fieldApiName: ORIGINFIELD })
originPicklistValues({
error,
data
}) {
if (data) {
this.originValues = data.values;
this.myValue = getFieldValue(data, ORIGINFIELD);
let dataList = [];

//Update all checkbox as true for new page
for (let index = 0; index < this.originValues.length; index++) {

let tempLst = Object.assign({}, this.originValues[index]);
tempLst.checkedBoolean = false;
dataList.push(tempLst);
}
this.originValues = dataList;
}
}


/*wire method to get current record origin value */
@wire(getRecord, { recordId: '$recordId', fields: [ORIGINFIELD] })
Originsss(
{ error, data }
) {
let dataList = [];
if (data && this.originValues.length !== 0 && this.recordId !== undefined) {
this.myValue = getFieldValue(data, ORIGINFIELD);

for (let index = 0; index < this.originValues.length; index++) {
//Update Appropriate checkbox as true for edit page
let tempLst = Object.assign({}, this.originValues[index]);
if (this.myValue === tempLst.value) {
tempLst.checkedBoolean = true;
}
else {
tempLst.checkedBoolean = false;
}
dataList.push(tempLst);

}
this.originValues = dataList;
}

}
/* method to get the checkbox value */
handleChange(event) {
this.value = event.detail.value;
}

/* Method to save the record */
handleSubmit(event) {
event.preventDefault(); // stop the form from submitting
const fields = event.detail.fields;
fields.Origin = this.value;
this.template.querySelector('lightning-record-edit-form').submit(fields);
}

/* Method to redirect the case standard view */
handleSucess(event) {
this[NavigationMixin.Navigate]({
type: 'standard__recordPage',
attributes: {
recordId: event.detail.id,
objectApiName: 'Case',
actionName: 'view'
}
});
const evt = new ShowToastEvent({
message: "case has been created sucessfully",
variant: "success",
});
this.dispatchEvent(evt);
}


}


GitHub :
Demo :




Creating Account ,Contact & Case in single transaction with Multiple Steps in LWC

When we work with forms which is having multiple object ,its suggested practice that we split the form into multiple screens.

Here we will see , how to create Account,Contact & Case record in single click using multi page forms.

Its built with below component structure.

Parent Component :
  •       multipageForm  -This is the Parent container
Child Component :
  •      accountForm    This is the child component which contain Account related fields
  •      ContactsForm   This is the child component which contain Contact related fields
  •      caseForm          This is the child component which contain Case related fields

multipageForm.html

<template>

<!--Loading Spinner-->
<div class="spinner">
<template if:true={isLoading}>
<lightning-spinner alternative-text="Loading" variant="brand" size="large">
</lightning-spinner>
</template>
</div>

<!--Progress indicator-->
<lightning-progress-indicator current-step={currentStep} type="path" variant="base">
<lightning-progress-step label="Account" value="1"> </lightning-progress-step>
<lightning-progress-step label="Contact" value="2"> </lightning-progress-step>
<lightning-progress-step label="Case" value="3"> </lightning-progress-step>
</lightning-progress-indicator>

<!--Step 1 : Account Form-->
<div class="stepOne">
<c-account-form class="acntForm" onaccountid={contactCreation}></c-account-form>
<lightning-button class="slds-m-top_small" label="Next" onclick={goToStepTwo}>
</lightning-button>
</div>

<!--Step 2 : Contact Form-->
<div class="stepTwo slds-hide">
<c-contacts-form class="contactForm" oncontactid={caseCreation}></c-contacts-form>
<lightning-button class="slds-m-top_small" label="Previous" onclick={goBackToStepOne}>
</lightning-button>
<lightning-button class="slds-m-top_small" label="Next" onclick={goToStepThree}>
</lightning-button>
</div>
<!--Step 3 : Case Form-->
<div class="stepThree slds-hide">
<c-case-form class="caseForm"></c-case-form>
<lightning-button class="slds-m-top_small" label="Previous" onclick={goBackToStepTwo}>
</lightning-button>
<lightning-button class="slds-m-top_small" label="Save" onclick={handleSave}>
</lightning-button>
</div>


</template>


multipageForm.js

import { LightningElement,api,track } from 'lwc';

export default class MultiPageForm extends LightningElement {
@api recordId;
@track currentStep;
@track accountId;
@track contactId;
isloading = false;

goBackToStepOne() {
this.currentStep = '1';
this.template.querySelector('div.stepTwo').classList.add('slds-hide');
this.template
.querySelector('div.stepOne')
.classList.remove('slds-hide');
}

goToStepTwo() {
this.currentStep = '2';
this.template.querySelector('div.stepOne').classList.add('slds-hide');
this.template
.querySelector('div.stepTwo')
.classList.remove('slds-hide');
}
goBackToStepTwo() {
this.currentStep = '2';
this.template.querySelector('div.stepThree').classList.add('slds-hide');
this.template
.querySelector('div.stepTwo')
.classList.remove('slds-hide');
}
goToStepThree() {
this.currentStep = '3';
this.template.querySelector('div.stepTwo').classList.add('slds-hide');
this.template
.querySelector('div.stepThree')
.classList.remove('slds-hide');
}
/*Method to create new Account */
handleSave(){
this.isloading = true;
this.template.querySelector(".acntForm").handleSubmit();
}
/*Method to create new Contact */
contactCreation(event){
this.accountId = event.detail;
this.template.querySelector(".contactForm").accountId = this.accountId ;
this.template.querySelector(".contactForm").handleSubmit();
}
/*Method to create new Case */
caseCreation(event){
this.contactId = event.detail;
this.template.querySelector(".caseForm").contactId = this.contactId ;
this.template.querySelector(".caseForm").accountId = this.accountId ;
this.template.querySelector(".caseForm").handleSubmit();
this.isloading = false;
}
}


accountForm.html

<template>
<lightning-record-edit-form class="Account" object-api-name="Account" onsuccess={handleSucess}>
<lightning-input-field field-name="Name" onchange={handleNameChange}>
</lightning-input-field>
</lightning-record-edit-form>
</template>

accountForm.js

import { LightningElement, track, api } from 'lwc';

export default class AccountForm extends LightningElement {

@track fields = {};

@api handleSubmit() {
this.template.querySelector('lightning-record-edit-form').submit(this.fields);
}

handleNameChange(event) {
this.fields.Name = event.target.value;
}

handleSucess(event) {
const accountId = event.detail.id;
const selectEvent = new CustomEvent('accountid', {
detail: accountId
});
this.dispatchEvent(selectEvent);
}
}

contactForm.html

<template>
<lightning-record-edit-form class="Contact" object-api-name="Contact" onsuccess={handleSucess}>
<lightning-input-field field-name="FirstName" onchange={firstNameChange}>
</lightning-input-field>
<lightning-input-field field-name="LastName" onchange={lastNameChange}>
</lightning-input-field>
<lightning-input-field field-name="Email" onchange={emailChange}>
</lightning-input-field>
</lightning-record-edit-form>
</template>


contactForm.js

import { LightningElement, api, track } from 'lwc';

export default class ContactsForm extends LightningElement {

@api accountId;
@track fields = {};

@api handleSubmit() {
this.fields.AccountId = this.accountId;
this.template.querySelector('lightning-record-edit-form').submit(this.fields);
}

handleSucess(event) {
const contactId = event.detail.id;
const selectEvent = new CustomEvent('contactid', {
detail: contactId
});
this.dispatchEvent(selectEvent);
}

firstNameChange(event) {
this.fields.FirstName = event.target.value;
}
lastNameChange(event) {
this.fields.LastName = event.target.value;
}
emailChange(event) {
this.fields.Email = event.target.value;
}

}


caseForm.html

<template>
<lightning-record-edit-form class="Case" object-api-name="Case" onsuccess={handleSucess}>
<lightning-input-field field-name="Origin" onchange={handleOriginChange}>
</lightning-input-field>
<lightning-input-field field-name="Subject" onchange={handleSubjectChange}>
</lightning-input-field>
<lightning-input-field field-name="Description" onchange={handleDescriptionChange}>
</lightning-input-field>
</lightning-record-edit-form>
</template>


caseForm.js

import { LightningElement,api,track } from 'lwc';
import { NavigationMixin } from 'lightning/navigation';
import { ShowToastEvent } from 'lightning/platformShowToastEvent';

export default class CaseForm extends NavigationMixin(LightningElement) {
@api contactId;
@api accountId;
@track fields ={};

@api handleSubmit(){
this.fields.ContactId = this.contactId;
this.fields.AccountId = this.accountId;
this.template.querySelector('lightning-record-edit-form').submit(this.fields);
}

handleSubjectChange(event){
this.fields.Subject =event.target.value;
}
handleDescriptionChange(event){
this.fields.Description =event.target.value;
}
handleOriginChange(event){
this.fields.Origin =event.target.value;
}

handleSucess (){
this[NavigationMixin.Navigate]({
type: 'standard__recordPage',
attributes: {
recordId: this.accountId,
objectApiName: 'Account',
actionName: 'view'
}
});
const evt = new ShowToastEvent({
message: "Account,Contact & Case has been created sucessfully",
variant: "success",
});
this.dispatchEvent(evt);
}

}


Demo :



GitHub :



Custom HTML data table with row action in LWC


In this post, we will see how to create Html data table in LWC with dynamic row actions.

ContactUtilities Apex class

public with sharing class ContactUtilities {
@AuraEnabled(Cacheable = false)
public static List<Contact> getContacts(Id sourceAccount){
return [SELECT Id,Name,Account.Name,LastName,FirstName,Email,Phone,MobilePhone
From Contact where AccountId =: sourceAccount];
}
}


<template>

<!--Loading Spinner-->
<div class="spinner">
<template if:true={isLoading}>
<lightning-spinner alternative-text="Loading" variant="brand" size="large">
</lightning-spinner>
</template>
</div>

<lightning-card class="" title="Contact List View">
<!-- New Contact Button-->
<div class="slds-media__body">
<div slot="actions" class="slds-float--right">
<lightning-button variant="neutral" label="New" title="New"
onclick={navigateToNewPage} class="slds-m-right_small ">
</lightning-button>
</div>
</div> <br/><br/>

<!--Contact List table starts-->

<template if:true={renderTable}>
<div class="tableDiv">
<div class={tableStyle}>
<table aria-describedby="conatact-list" class="slds-table slds-table_bordered ">

<!--Header of the table-->
<thead>
<tr class="slds-line-height_reset">
<th class="slds-size_1-of-6 " scope="col">
<div class="slds-truncate " title="First Name">First Name</div>
</th>
<th class="slds-size_1-of-6 " scope="col">
<div class="slds-truncate " title="Last Name">Last Name</div>
</th>
<th class="slds-size_1-of-6 " scope="col">
<div class="slds-truncate " title="Email">Email</div>
</th>
<th class="slds-size_1-of-6" scope="col">
<div class="slds-truncate " title="Phone">Phone
</div>
</th>
<th class="slds-size_1-of-6" scope="col">
<div class="slds-truncate " title="Mobile">Mobile
</div>
</th>
<th class="slds-size_1-of-6" scope="col">
<div class="slds-truncate " title=""></div>
</th>
</tr>
</thead>

<!--Body of the table-->
<tbody>
<template for:each={contactList} for:item="item" for:index="indexVar">
<tr key={item.Id} class="slds-hint-parent">
<td class="slds-size_1-of-6">
<div>
{item.FirstName}
</div>
</td>
<td class="slds-size_1-of-6">
<div>
{item.LastName}
</div>
</td>
<td class="slds-size_1-of-6">
<div>
{item.Email}
</div>
</td>
<td class="slds-size_1-of-6">
<div>
{item.Phone}
</div>
</td>
<td class="slds-size_1-of-6">
<div>
{item.MobilePhone}
</div>
</td>
<td class="slds-size_1-of-6">
<div class="buttonMenu">
<lightning-button-menu alternative-text="Toggle menu">
<P onclick={navigateToRecordEditPage} data-recid={item.Id}>
<lightning-menu-item label="Edit">
</lightning-menu-item>
</P>
<p onclick={deleteContact} data-recid={item.Id}>
<lightning-menu-item label="Delete">
</lightning-menu-item>
</p>
</lightning-button-menu>
</div>
</td>
</tr>
</template>
</tbody>
</table>
</div>
</div>

</template>
</lightning-card>
</template>


import { LightningElement, api, track } from 'lwc';
import getContacts from '@salesforce/apex/ContactUtilities.getContacts';
import { NavigationMixin } from 'lightning/navigation';
import { deleteRecord } from 'lightning/uiRecordApi';
import { ShowToastEvent } from 'lightning/platformShowToastEvent';
import { encodeDefaultFieldValues } from 'lightning/pageReferenceUtils';


export default class CustomDataTable extends NavigationMixin(LightningElement) {

@api recordId;
isloading;
@track contactList;
renderTable = false;

connectedCallback() {
this.isLoading = true;
getContacts({ sourceAccount: this.recordId })
.then(result => {
this.contactList = result;
if (this.contactList.length === 0) {
this.renderTable = false;
}
else {
this.renderTable = true;
}
})
this.isLoading = false;
}

//To navigate to record edit page for selected record
navigateToRecordEditPage(event) {
this[NavigationMixin.Navigate]({
type: 'standard__recordPage',
attributes: {
recordId: event.currentTarget.dataset.recid,
objectApiName: 'Contact',
actionName: 'edit'
}
});
}

//To delete the selected contact
deleteContact(event) {
this.isLoading = true;
deleteRecord(event.currentTarget.dataset.recid)
.then(() => {
this.dispatchEvent(
new ShowToastEvent({
title: 'Success',
message: 'Record Is Deleted',
variant: 'success',
}),
);
this.connectedCallback();
this.isLoading = false;
})
.catch(error => {
this.dispatchEvent(
new ShowToastEvent({
title: 'Error',
message: error.message,
variant: 'error',
}),
);
this.connectedCallback();
this.isLoading = false;
});
}

// To navigate to contact new functionality aura component
navigateToNewPage() {
const defaultValues = encodeDefaultFieldValues({
AccountId: this.recordId

});
this[NavigationMixin.Navigate]({
type: 'standard__objectPage',
attributes: {
objectApiName: 'Contact',
actionName: 'new'
},
state: {
defaultFieldValues: defaultValues
}
});
}


}


<?xml version="1.0" encoding="UTF-8"?>
<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata">
<apiVersion>48.0</apiVersion>
<isExposed>True</isExposed>
<targets>
<target>lightning__RecordPage</target>
</targets>
<targetConfigs>
<targetConfig targets="lightning__RecordPage">
<objects>
<object>Account</object>
</objects>
</targetConfig>
</targetConfigs>
</LightningComponentBundle>

GitHub :

Demo