Hello Everyone, Today, In this post i am going to create a lightning web component. By using this web component you can search and add contact to account from account record details page. So let's get started,

Search and add contacts to account in lightning web component

To search contacts in this lwc, I am using SOSL query. By using this query data bind to the picklist.

SearchAndAddHandler.apxc

 public class SearchAndAddHandler {    
@AuraEnabled
public static List<sObject> findRecord(List<String> fields, String searchTerm){
String searchKeyword = searchTerm + '*';
String returningQuery = 'Contact ( Id, '+String.join(fields,',')+')';
String query = 'FIND :searchKeyword IN ALL FIELDS RETURNING '+returningQuery+' LIMIT 20';
System.debug(' query '+query);
List<List<sObject>> searchRecords = Search.Query(Query);
return searchRecords.get(0);
}

@AuraEnabled
public static void updateContact( Id contactId, Id accountId){
Contact c = new Contact();
c.Id = contactId;
c.AccountId = accountId;
update c;
}
}
SearchAndAddContactLWC.html
 <template>
<lightning-card icon-name="utility:dynamic_record_choice" title="Search and Add Contacts">
<lightning-spinner if:true={isLoading} alternative-text="Loading" size="small"></lightning-spinner>
<div class="slds-form-element">
<div class="slds-p-horizontal_medium">
<lightning-input type="text" onchange={handleInputChange} placeholder={placeholder}>
</lightning-input>
</div>
<ul class="slds-listbox slds-listbox_vertical" style="margin-left:6px;margin-right:6px;">
<template if:true={searchRecords} for:each={searchRecords} for:item="record" for:index="index">
<li class="slds-listbox__item" data-record-id={record.Id} key={record.Id}>
<div data-id={record.Id}
class="slds-media slds-listbox__option slds-listbox__option_entity slds-listbox__option_has-meta"
role="option">
<span class="slds-media__figure slds-listbox__option-icon">
<span class="slds-icon_container slds-icon-standard-account">
<svg class="slds-icon slds-icon_small" aria-hidden="true">
<use xlink:href={ICON_URL}></use>0
</svg>
</span>
</span>
<span class="slds-media__body">
<span class="slds-listbox__option-text slds-listbox__option-text_entity">
{record.FIELD1}
</span>
<span class="slds-listbox__option-meta slds-listbox__option-meta_entity">
{record.FIELD2} &nbsp; {record.FIELD3}
</span>
</span>
<span if:false={record.FIELD4}>
<lightning-button label="Add to Account" title="Download action" value={record.Id}
icon-name="utility:add" class="slds-m-left_x-small" onclick={addtoaccount}>
</lightning-button>
</span>
<span if:true={record.FIELD4}>
<lightning-button label="Add to Account" title="Download action" value={record.Id}
icon-name="utility:add" disabled="true" class="slds-m-left_x-small"
onclick={addtoaccount}>
</lightning-button>
</span>
</div>
</li>
</template>
</ul>
</div>
<br/>
</lightning-card>
</template>
SearchAndAddContactLWC.js
 import { LightningElement, track, api } from 'lwc';
import { ShowToastEvent } from 'lightning/platformShowToastEvent';
import findRecord from '@salesforce/apex/SearchAndAddHandler.findRecord';
import updateContact from '@salesforce/apex/SearchAndAddHandler.updateContact';
const DELAY = 300;
export default class SearchAndAddContactLWC extends LightningElement {
@api recordId;
placeholder = 'Search (type atleast 2 char)';
fields = ['Name', 'Email', 'Phone', 'AccountId'];
@track error;
searchTerm;
delayTimeout;
@track searchRecords;
isLoading = false;
ICON_URL = '/apexpages/slds/latest/assets/icons/standard-sprite/svg/symbols.svg#contact';

handleInputChange(event) {
window.clearTimeout(this.delayTimeout);
const searchKey = event.target.value;
this.delayTimeout = setTimeout(() => {
if (searchKey.length >= 2) {
this.isLoading = true;
findRecord({
fields: this.fields,
searchTerm: searchKey
}).then(result => {
let stringResult = JSON.stringify(result);
let allResult = JSON.parse(stringResult);
allResult.forEach(record => {
record.FIELD1 = record['Name'];
record.FIELD2 = record['Email'];
record.FIELD3 = record['Phone'];
record.FIELD4 = this.accountIdCheck(record['AccountId']);
});
this.searchRecords = allResult;
}).catch(error => {
console.error('Error:', error);
}).finally(() => {
this.isLoading = false;
});
}
}, DELAY);
}

addtoaccount(event) {
let selectedConId = event.target.value;
updateContact({
contactId: selectedConId,
accountId: this.recordId
}).then(result => {
this.error = undefined;
const evt = new ShowToastEvent({
title: 'Success!',
message: 'Contact Added Successfully!',
variant: 'success',
});
this.dispatchEvent(evt);
for (var i = 0; i < this.searchRecords.length; i++) {
if (this.searchRecords[i].Id === selectedConId) {
this.searchRecords[i].FIELD4 = true;
}
}
eval("$A.get('e.force:refreshView').fire();");
}).catch(error => {
console.error('Error:', error);
})
}

accountIdCheck(accId) {
if (accId === this.recordId)
return true;
return false
}
}
SearchAndAddContactLWC.js-meta.xml
 <?xml version="1.0"?>
<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata">
<apiVersion>51.0</apiVersion>
<isExposed>true</isExposed>
<masterLabel>SearchAndAddContact</masterLabel>
<targets>
<target>lightning__RecordPage</target>
</targets>
<targetConfigs>
<targetConfig targets="lightning__RecordPage">
<objects>
<object>Account</object>
</objects>
</targetConfig>
</targetConfigs>
</LightningComponentBundle>

Note: You can see object configuration in above xml file. This will allow component only for account record page. 

Add this component to account record details page to see the output.

Output:

Hope you like this post, for any feedback or suggestions please feel free to comment. I would appreciate your feedback and suggestions.

Happy Coding

Thank you.