You need to sign in to do that
Don't have an account?
Samantha Lisk 10
LWC Not Rendering in Record Page, No Error Appears
Hi All,
I'm trying to build a Google Maps LWC to show the location of an Account on the Account's record page. However, the component isn't rendering, even though I've added it to the page. No error appears. Screenshots and code below.
companyMap.html:
<template> <template if:true={record}> <lightning-card title="Location" icon-name="standard:address"> <lightning-map data={accounts.data} name={name} map-markers={mapMarkers} ></lightning-map> </lightning-card> </template> </template>
companyMap.js:
import { LightningElement, wire, track, api } from 'lwc'; import getAccount from '@salesforce/apex/AccountListController.getAccount'; const fields = [ 'Account.Name', 'Address__c', 'Account.BillingStreet', 'Account.BillingCity', 'Account.BillingState', 'Account.BillingPostalCode', 'Account.BillingCountry' ]; export default class CompanyMap extends LightningElement { @api recordId; accountId; address; @track record; @track name; @track billingStreet; @track billingCity; @track billingState; @track billingPostalCode; @track billingCountry; mapMarkers; @wire(getAccount, { recordId: '$accountId', fields: fields }) wiredRecord({ error, data }) { if (data) { this.record = data; const account = data.fields; this.address = `${account.BillingStreet.value}, ${account.BillingCity.value}, ${account.BillingState.value}, ${account.BillingPostalCode.value}, ${account.BillingCountry.value}`; this.mapMarkers = [ { location: `${account.address.value}`, title: `${account.Name.value}`, mapIcon: { path: 'M1472 992v480q0 26-19 45t-45 19h-384v-384h-256v384h-384q-26 0-45-19t-19-45v-480q0-1 .5-3t.5-3l575-474 575 474q1 2 1 6zm223-69l-62 74q-8 9-21 11h-3q-13 0-21-7l-692-577-692 577q-12 8-24 7-13-2-21-11l-62-74q-8-10-7-23.5t11-21.5l719-599q32-26 76-26t76 26l244 204v-195q0-14 9-23t23-9h192q14 0 23 9t9 23v408l219 182q10 8 11 21.5t-7 23.5z', fillColor: '#f28b00', fillOpacity: 1, strokeWeight: 1, scale: 0.02 } } ]; this.error = undefined; } else if (error) { this.error = error; this.record = undefined; } console.log(data); } }AccountListController.cls:
public with sharing class AccountListController { @AuraEnabled(cacheable=true) public static List<Account> getAccount() { return [ SELECT Id, Name, BillingStreet, BillingCity, BillingState, BillingPostalCode, BillingCountry FROM Account WITH SECURITY_ENFORCED ORDER BY LastModifiedDate DESC LIMIT 50 ]; } }
companyMap.js-meta.xml:
<?xml version="1.0" encoding="UTF-8"?> <LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata"> <apiVersion>52.0</apiVersion> <isExposed>true</isExposed> <targets> <target>lightning__RecordPage</target> </targets> <targetConfigs> <targetConfig targets="lightning__RecordPage"> <objects> <object>Account</object> </objects> </targetConfig> </targetConfigs> </LightningComponentBundle>
Thanks to Nathan Shulman on the Ohana Slack for his help in resolving this issue! Here's the working code:
.cls
.js .htmlAll Answers
Please use below code :-
.html
.js
Apex class:-
if you need any assistanse, Please let me know!!
Kindly mark my solution as the best answer if it helps you.
Thanks
Mukesh
Thank you. The component is now rendering; however, there are 2 issues:
1) The component is not placing a map-marker at the address; and
2) This error is appearing when the page loads:
The value of BillingStreet is undefined?
Samantha
Thanks to Nathan Shulman on the Ohana Slack for his help in resolving this issue! Here's the working code:
.cls
.js .htmlhtml part :
<template>
<div class="notification-container">
<template for:each={notifications} for:item="notification">
<div key={notification.key} class={notification.cssClass} role="alert">
<div class="slds-notify__content">
<h2 class="slds-text-heading_small">{notification.title}</h2>
<p>{notification.message}</p>
</div>
</div>
</template>
</div>
<div class="noteApp flex">
<div class="notecard flex-items" onclick={createNote}>
<div class="dottedCircle">
<lightning-icon icon-name='utility:add' alternative-text='add' size='large' title='add'
class="custom-icon"></lightning-icon>
</div>
<h2 class="slds-var-m-top_medium">Add New Note</h2>
</div>
<template for:each={noteList} for:item="note" >
<div key={note.Id} class="notecard slds-var-m-bottom_medium">
<header>
<h2 class="slds-truncate">{note.Name}</h2>
</header>
<div class="description">
<lightning-formatted-rich-text value={note.Description__c}></lightning-formatted-rich-text>
</div>
<footer class="footer">
<div class="Date">{note.formateDate}</div>
<div>
<lightning-icon icon-name='action:edit' alternative-text='edit' size='small' title='edit'
class="custom-icons cursor" onclick={handleEdit} data-recordid={note.Id}></lightning-icon>
<!-- we are using data-recordid={note.Id} because we want to know which record is selected for edit -->
<lightning-icon icon-name='action:delete' alternative-text='delete' size='small' title='delete'
class="slds-var-m-left_medium custom-iconss cursor" onclick={handleDelete} data-recordid={note.Id}></lightning-icon>
</div>
</footer>
</div>
</template>
</div>
<template if:true={showModal}>
<c-modal>
<h1 slot="header" class="slds-modal__title">{headerName}</h1>
<form>
<lightning-input type="text" label="Title" name="Name" value={noteRecord.Name}
class="slds-var-m-bottom_medium" onchange={handleChange}></lightning-input>
<lightning-input-rich-text name="Description__c" value={noteRecord.Description__c} label-visible
formats={formats} onchange={handleChange}>
</lightning-input-rich-text>
</form>
<footer slot="footer">
<button class="slds-button slds-button_neutral" onclick={handelCancel}>Cancel</button>
<button class="slds-button slds-button_brand" onclick={handleSave}
disabled={isFormInvalid}>{headerName}</button>
</footer>
</c-modal>
</template>
</template>
js part:
import { LightningElement, wire } from 'lwc';
import createNoteRecords from '@salesforce/apex/CreateNoteRecord.createNoteRecords';
import { refreshApex } from '@salesforce/apex';
import getAllNotes from '@salesforce/apex/CreateNoteRecord.getAllNotes';
import editNoteRecord from '@salesforce/apex/CreateNoteRecord.editNoteRecord';
import deleteNoteRecord from '@salesforce/apex/CreateNoteRecord.deleteNoteRecord';
import { ShowToastEvent } from 'lightning/platformShowToastEvent';
const NOTE_FORM = {
Name:"",
Description__c:""
}
export default class NoteTakingApp extends LightningElement {
noteList=[];
refreshData;
notifications = [];
showModal = false;
noteRecord = NOTE_FORM;
formats = [
'font',
'size',
'bold',
'italic',
'underline',
'strike',
'list',
'indent',
'align',
'link',
'clean',
'table',
'header',
'color',
];
@wire(getAllNotes)
wiredNotes(result) {
this.refreshData = result;
if (result.data) {
this.noteList = result.data.map(item => ({
...item,
formattedDate: new Date(item.LastModifiedDate).toDateString()
}));
} else if (result.error) {
console.error('Error', result.error);
this.showToast('Error', 'An error occurred', 'error');
}
}
createNote() {
console.log('Before showModal:', this.selectedRecordId);
this.showModal = true;
console.log('After showModal:', this.selectedRecordId);
}
handelCancel() {
console.log('Before handelCancel:', this.selectedRecordId);
this.showModal = false;
this.noteRecord = NOTE_FORM;
this.selectedRecordId = null;
console.log('After handelCancel:', this.selectedRecordId);
}
handleChange(event){
const{name,value} = event.target;
this.noteRecord = {...this.noteRecord, [name]:value}
}
get isFormInvalid(){
return !(this.noteRecord && this.noteRecord.Description__c && this.noteRecord.Name);
}
async handleSave(event) {
event.preventDefault();
try {
let result;
if (this.selectedRecordId) {
// If there's a selectedRecordId, it means you're editing an existing note
result = await editNoteRecord({
noteId: this.selectedRecordId,
name: this.noteRecord.Name,
description: this.noteRecord.Description__c
});
} else {
// If there's no selectedRecordId, it means you're creating a new note
result = await createNoteRecords({
title: this.noteRecord.Name,
description: this.noteRecord.Description__c
});
}
if (result) {
if (this.selectedRecordId) {
// Update the noteList with the edited record
const editedNoteIndex = this.noteList.findIndex(item => item.Id === this.selectedRecordId);
refreshApex(this.refreshData);
if (editedNoteIndex !== -1) {
this.noteList[editedNoteIndex] = {
...this.noteList[editedNoteIndex],
Name: this.noteRecord.Name,
Description__c: this.noteRecord.Description__c
};
}
this.showToast('Success', 'Note updated successfully', 'success');
} else {
// Add the new note to the list
const formateDate = new Date().toDateString();
const newNote = {
Id: result, // Assuming the result contains the newly created note's Id
Name: this.noteRecord.Name,
Description__c: this.noteRecord.Description__c,
formateDate: formateDate
};
this.noteList = [...this.noteList, newNote];
this.showToast('Success', 'Note created successfully', 'success');
}
this.selectedRecordId = null;
this.showModal = false;
this.noteRecord = { ...NOTE_FORM };
} else {
this.showToast('Warning', 'Note operation failed', 'warning');
}
} catch (error) {
console.error("Error handling note operation:", error);
this.showToast('Error', 'An error occurred', 'error');
}
}
showToast(title, message, variant) {
const event = new ShowToastEvent({
title: title,
message: message,
variant: variant
});
this.dispatchEvent(event);
const newNotification = {
key: Date.now(),
title: title,
message: message,
variant: variant,
cssClass: this.computeNotificationClass(variant)
};
this.notifications = [...this.notifications, newNotification];
// Set a timeout to remove the notification after 5 seconds
setTimeout(() => {
this.notifications = this.notifications.filter(notification => notification.key !== newNotification.key);
}, 5000); // 5000 milliseconds = 5 seconds
}
computeNotificationClass(variant) {
if (variant === 'success') {
return 'slds-notify slds-notify_success';
} else if (variant === 'warning') {
return 'slds-notify slds-notify_warning';
} else if (variant === 'error') {
return 'slds-notify slds-notify_error';
}
return 'slds-notify'; // Default class if variant is not recognized
}
handleEdit(event) {
const recordId = event.target.dataset.recordid;
console.log('Clicked recordId:', recordId);
console.log('this.noteList:', this.noteList);
console.log('event.target.dataset:', event.target.dataset);
// we are using data set because we want to get data from data-recordid={note.Id} and there it will pick the recordid.
// we can use like that also ---> event.target.dataset.recordid;
// Find the note record with the matching Id
const noteRecord = this.noteList.find(item => item.Id === recordId);
if (noteRecord) {
// Set the noteRecord values if found
this.noteRecord = {
Name: noteRecord.Name,
Description__c: noteRecord.Description__c
};
this.selectedRecordId = recordId;
this.showModal = true;
console.log('After handleEdit:', this.selectedRecordId);
} else {
console.error("Note record not found for editing.");
}
}
get headerName(){
return this.selectedRecordId ? "Update Note" : "Add Note";
}
editNoteRecord(noteId){
const { Name, Note_Description__c } = this.noteRecord;
editNoteRecord({ "noteId": noteId, "name": Name, "description": Note_Description__c })
.then(() => {
this.showModal = false;
this.selectedRecordId = null; // Reset selectedRecordId to null
this.showToastMsg("Note Updated Successfully!!", 'success');
})
.catch(error => {
console.error("error in updating", error);
this.showToastMsg(error.message.body, 'error');
});
}
handleDelete(event) {
const recordId = event.target.dataset.recordid;
deleteNoteRecord({ noteId: recordId })
.then(result => {
if (result) {
this.noteList = this.noteList.filter(item => item.Id !== recordId);
this.showToast('Success', 'Note deleted successfully', 'success');
} else {
this.showToast('Warning', 'Note deletion failed', 'warning');
}
})
.catch(error => {
console.error("Error deleting note:", error);
this.showToast('Error', 'An error occurred', 'error');
});
}
}
When I want to edit then it is showing recordid: true and I can not edit my page but when I refresh my page and again edit then it is showing recordid and it is same for delete part also
. can you tell me why?