My idea of implementation is based on - Evaluation of approach to navigate between 3 LWC pages
I have 2 pages currently. Each page is a component. The parent component(InterviewProcess) contains these two child components, and I am traversing between them using next / previous button.
Page 1 : LWC - <c-initiate-interview>
<template>
<div class="slds-grid slds-wrap">
<div class="slds-col">
<div class="slds-m-top_medium slds-m-bottom_x-large">
<div class="slds-p-around_medium lgc-bg">
<lightning-input type="text" name="firstName" label="First Name" placeholder="type here..." onchange={handleFormInputChange} required>
</lightning-input>
</div>
<div class="slds-p-around_medium lgc-bg">
<lightning-input type="text" name="lastName" label="Last Name" placeholder="type here..." onchange={handleFormInputChange} required>
</lightning-input>
</div>
<div class="slds-p-around_medium lgc-bg">
<lightning-input type="text" name="company" label="Current Company" placeholder="type here..." onchange={handleFormInputChange}>
</lightning-input>
</div>
<div class="slds-p-around_medium lgc-bg">
<lightning-textarea name="notes" label="Notes" placeholder="type here..." onchange={handleFormInputChange}></lightning-textarea>
</div>
<div class="slds-p-around_medium lgc-bg">
<lightning-input type="file" label="Attachment" accept="image/png, image/jpg, .zip" onchange={handleFormInputChange}></lightning-input>
</div>
</div>
</div>
<div class="slds-col">
<div class="slds-m-top_medium slds-m-bottom_x-large">
<div class="slds-p-around_medium lgc-bg">
<lightning-dual-listbox name="roles" label="Roles" source-label="Available"
selected-label="Selected" field-level-help="Select role for the Interview" options={options}
onchange={handleFormInputChange}></lightning-dual-listbox>
</div>
<div class="slds-p-around_medium lgc-bg">
<lightning-combobox name="level" label="Difficulty Level" value="" placeholder="Select Level"
options={levels} onchange={handleFormInputChange} required></lightning-combobox>
</div>
</div>
</div>
</div>
</template>
JS:
import { LightningElement, wire } from 'lwc';
import { NavigationMixin, CurrentPageReference } from 'lightning/navigation';
export default class InitiateInterview extends LightningElement {
roles = [];
level = 'beginner';
firstName;
lastName;
company = '';
notes = '';
// Files
fileName;
fileContent = '';
get options() {
return [
{ label: 'Developer', value: 'Developer' },
{ label: 'Technical Architect', value: 'Technical Architect' },
{ label: 'Solution Architect', value: 'Solution Architect' },
{ label: 'Business Analyst', value: 'Business Analyst' },
{ label: 'Scrum Master', value: 'Scrum Master' },
{ label: 'PM', value: 'PM' },
];
}
get levels() {
return [
{ label: 'Beginner', value: 'Beginner' },
{ label: 'Intermediate', value: 'Intermediate' },
{ label: 'Advanced', value: 'Advanced' },
];
}
async handleFormInputChange(event) {
switch (event.target.name) {
case 'firstName':
this.firstName = event.target.value;
break;
case 'lastName':
this.lastName = event.target.value;
break;
case 'company':
this.company = event.target.value;
break;
case 'notes':
this.notes = event.target.value;
break;
case 'roles':
this.roles = event.target.value;
break;
case 'level':
this.level = event.target.value;
break;
}
if (event.target.files) {
this.fileName = event.target.files[0].name;
this.fileContent = await this.readFile(event.target.files[0]);
}
this.createInitiateInterviewEvent();
}
readFile(file) {
return new Promise((resolve, reject) => {
const fileReader = new FileReader();
fileReader.onload = () => {
resolve(fileReader.result.split(/base64,/)[1]);
};
fileReader.onerror = () => {
reject(fileReader.error);
};
fileReader.readAsDataURL(file);
});
}
createInitiateInterviewEvent() {
let isValid = false;
if ((typeof this.firstName != 'undefined' && this.firstName.length != 0) &&
typeof this.lastName != 'undefined' && this.lastName.length != 0) {
isValid = true;
}
const nextEvnt = new CustomEvent('initiateinterview', {
detail: {
page: "1", firstName: this.firstName, lastName: this.lastName, company: this.company, reqValidation: isValid,
notes: this.notes, roles: this.roles, level: this.level, fileName: this.fileName, file: this.fileContent
}
});
this.dispatchEvent(nextEvnt);
}
}
Page 2: <c-interview-questions>
<template>
Interview Question Page
</template>
JS
import { LightningElement } from 'lwc';
export default class InterviewQuestions extends LightningElement {}
Parent Component: InterviewProcess.html
<template>
<lightning-card title="Interview" icon-name="standard:insights">
<template if:true={isInitiateInterviewPage}>
<c-initiate-interview oninitiateinterview={initiateInterview}></c-initiate-interview>
</template>
<template if:true={isInterviewQuesPage}>
<c-interview-questions></c-interview-questions>
</template>
<footer role="contentinfo" class="slds-p-around_medium">
<div class="slds-align_absolute-center ">
<lightning-button variant="brand" label="Cancel" title="Cancel" onclick={handleCancel}
icon-position="right" class="slds-m-left_x-small"></lightning-button>
<lightning-button variant="brand" label="Previous" title="Previous" onclick={handlePrevious}
icon-position="right" class="slds-m-left_x-small"></lightning-button>
<lightning-button variant="brand" label="Next" title="Next" onclick={handleNext} icon-position="right"
class="slds-m-left_x-small"></lightning-button>
</div>
</footer>
</lightning-card>
</template>
JS:
import { LightningElement } from 'lwc';
import createInterview from '@salesforce/apex/InitiateInterviewController.createInterview';
import { ShowToastEvent } from 'lightning/platformShowToastEvent'
import { reduceErrors } from 'c/ldsUtils';
export default class InterviewProcess extends LightningElement {
interviewInputs;
isInterviewQuesPage = false;
isInitiateInterviewPage = true;
page = 1;
initiateInterview(event) {
console.log('handling event in parent=> ' + JSON.stringify(event.detail));
this.interviewInputs = event.detail;
}
handlePrevious(event) {
this.isInitiateInterviewPage = true;
this.isInterviewQuesPage = false;
**// pre populate the values of previous page**
}
handleNext() {
if (this.interviewInputs) {
if (this.interviewInputs.reqValidation) {
createInterview({ candidateData: JSON.stringify(this.interviewInputs) })
.then(result => {
this.isInterviewQuesPage = true;
this.isInitiateInterviewPage = false;
this.dispatchEvent(
new ShowToastEvent({
title: result,
message: result,
variant: 'success'
})
);
})
.catch(error => {
this.error = error;
this.dispatchEvent(
new ShowToastEvent({
title: 'Error Occured',
message: reduceErrors(error).join(', '),
variant: 'error'
})
);
});
} else {
this.dispatchEvent(
new ShowToastEvent({
title: 'Please fill in the required fields',
variant: 'error'
})
);
}
}
}
}
Apex Controller: InitiateInterviewController.createInterview , Basically gets the JSON String and deserialize it. I plan to insert/update the Contact and Interview Object using the JSOn string and return some output [TBD].
Problem here: When I traverse from Page 2 to Page 1 , I am looking at an approach that will help me populate the values that user entered in first page. If I have created/updated a new contact when user clicked Next on page 1 then I would like to pre populate those values when user wants to go back to previous page.
On clicking previous , I am exploring an approach to pre populate the values that was selected before/ that the apex controller inserted/updated before.