carFilter and carCard Components

carFilter.html
				
					<template>
    <lightning-card title="Filters" icon-name="standard:calibration">
        <div class="slds-m-horizontal_medium">
            <lightning-input type="search" variant="standard" name="search" label="Search Key" placeholder="type here..." value={filters.searchKey}
                onchange={handleSearchKeyChange}></lightning-input>
            <section class="slider_section">
                <lightning-slider label="Max Price" step="100" value={filters.maxPrice} min="0" max="999999" onchange={handleMaxPriceChange} ></lightning-slider>
            </section>
            <section>
                <h2>Category</h2>
                 <template if:true={categories.data}>
                    <template for:each={categories.data.values} for:item="category">
                        <lightning-input key={category.value}
                        label={category.label}
                        type="checkbox"
                        checked
                        data-name="categories"
                        data-value={category.value}
                        onchange={handleCheckbox}
                        ></lightning-input>
                    </template>
                    
                 </template>
                 <template if:true={categories.error}>
                     <div>{CATEGORY_ERROR}</div>
                 </template>
            </section>
           <section>
                <h2>Make</h2>
               <template if:true={makeTypes.data}>
                    <template for:each={makeTypes.data.values} for:item="type">
                        <lightning-input key={type.value} 
                        type="checkbox" checked 
                        label={type.label} 
                        name="makeType"
                        data-name="makeType"
                        data-value={type.value}
                        onchange={handleCheckbox}></lightning-input>
                    </template>
                </template>
                <template if:true={makeTypes.error}>
                    <div>{MAKE_ERROR}</div>
                </template>
            </section>
        </div>
    </lightning-card>
</template>
				
			
carFilter.js
				
					import { LightningElement, wire } from 'lwc';
import {getObjectInfo, getPicklistValues} from 'lightning/uiObjectInfoApi'
import CAR_OBJECT from '@salesforce/schema/Car__c'
//car Schema
import CATEGORY_FIELD from '@salesforce/schema/Car__c.Category__c'
import MAKE_FIELD from '@salesforce/schema/Car__c.Make__c';

// Lightning Message Service and a message channel
import {publish,MessageContext} from 'lightning/messageService';
import CARS_FILTERED_MESSAGE from '@salesforce/messageChannel/CarsFiltered__c';

const CATEGORY_ERROR = 'Error Loading Categories';
const MAKE_ERROR = 'Error Loading Categories';

export default class CarFilter extends LightningElement {

    filters = {
        searchKey: '',
        maxPrice: 0
    }

    timer;

    // Load Context for LMS
    @wire(MessageContext)
    messageContext

    @wire(getObjectInfo, {objectApiName:CAR_OBJECT})
    carObjectInfo

    @wire(getPicklistValues, {
        recordTypeId:'$carObjectInfo.data.defaultRecordTypeId',
        fieldApiName:CATEGORY_FIELD
    })categories

    @wire(getPicklistValues,{
        recordTypeId:'$carObjectInfo.data.defaultRecordTypeId',
        fieldApiName:MAKE_FIELD
    })makeTypes
    
    handleSearchKeyChange(event) {
        console.log("search key=>"+event.target.value);
        this.filters = {...this.filters,"searchKey":event.target.value};
        this.sendDataToCarList();
    }
    handleMaxPriceChange(event) {
        console.log("price =>"+event.target.value);
        this.filters = {...this.filters,"maxPrice":event.target.value}
        this.sendDataToCarList();
    }
    handleCheckbox(event){
        const {name,value} = event.target.dataset;
        console.log("name=>"+name);
        console.log("value=>"+value);
        if(!this.filters.categories){
            const categories = this.categories.data.values.map(item=>item.value);
            const makeType = this.makeTypes.data.values.map(item=>item.value);
            this.filters = {...this.filters,categories,makeType} // we are using short hand notation it is similar to categories:categories,makeType:makeType
        }
        if(event.target.checked){
            console.log('if included=>',this.filters[name])
            if(!this.filters[name].includes(value)){
                this.filters[name] = [...this.filters[name],value]
            }
            console.log('after if included=>',this.filters[name])
        }else{
             console.log('inside else =>',this.filters[name])
            this.filters[name] = this.filters[name].filter(item=> item !== value)
        }
        this.sendDataToCarList();
    }
    sendDataToCarList(){
        window.clearTimeout(this.timer);
        this.timer= window.setTimeout(()=>{
            publish(this.messageContext,CARS_FILTERED_MESSAGE,{
            filters:this.filters
            });
        },400)
    }
}
				
			
carFilter.js-meta.xml
				
					<?xml version="1.0"?>
<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata">
	<apiVersion>57.0</apiVersion>
	<isExposed>true</isExposed>
	<masterLabel>Car Filter</masterLabel>
	<targets>
		<target>lightning__AppPage</target>
	</targets>
</LightningComponentBundle>
				
			
carCard.html
				
					<template>
	<lightning-card title={carName} icon-name="standard:apex_plugin">
		<template if:true={recordId}>
	    <lightning-button label="View" slot="actions"  onclick={handleNavigationToRecordPage}></lightning-button>
		<div class="slds-m-horizontal_medium">
			<img src={carPictureURL} alt="Car Picture"/>
			<lightning-record-view-form onload={handleRecordLoaded} record-id={recordId} density="compact"
				object-api-name="Car__c">
				<lightning-output-field field-name={categoryField}></lightning-output-field>
				<lightning-output-field field-name={makeField}></lightning-output-field>
				<lightning-output-field field-name={msrpField}></lightning-output-field>
				<section>Other Features</section>
				<lightning-output-field field-name={fuelTypeField}></lightning-output-field>
				<lightning-output-field field-name={controlField}></lightning-output-field>
				<lightning-output-field field-name={seatsField}></lightning-output-field>
			</lightning-record-view-form>
		</div>
		</template>
		<template if:false={recordId}>
		<p> <c-placeholder message="Select a car to see details"></c-placeholder></p>
		</template>
	</lightning-card>
</template>
				
			
carCard.js
				
					import { LightningElement,wire } from 'lwc';
import CAR_OBJECT from '@salesforce/schema/Car__c';
import Name_Field from '@salesforce/schema/Car__c.Name';
import Picture_URL_Field from '@salesforce/schema/Car__c.Picture_URL__c';
import Category_Field from '@salesforce/schema/Car__c.Category__c';
import Make_Field from '@salesforce/schema/Car__c.Make__c';
import MSRP_Field from '@salesforce/schema/Car__c.MSRP__c';
import Fuel_Type_Field from '@salesforce/schema/Car__c.Fuel_Type__c';
import Number_of_Seats_Field from '@salesforce/schema/Car__c.Number_of_Seats__c';
import Control_Field from '@salesforce/schema/Car__c.Control__c';
import {getFieldValue} from 'lightning/uiRecordApi';

import {NavigationMixin} from 'lightning/navigation'

// Lightning Message Service and a message channel
import {subscribe,unsubscribe,MessageContext} from 'lightning/messageService';
import CARS_SELECTED_MESSAGE from '@salesforce/messageChannel/CarsSelected__c';

export default class CarCard extends NavigationMixin(LightningElement) {
    
    categoryField = Category_Field;
    makeField = Make_Field;
    msrpField = MSRP_Field
    fuelTypeField = Fuel_Type_Field;
    seatsField = Number_of_Seats_Field;
    controlField = Control_Field;

    // car name and picture url we are extracting differently because we need a different format in ui
    carName;
    carPictureURL;
    carSelectionSubscription;
    recordId;

    // Load Context for LMS
    @wire(MessageContext)
    messageContext

    handleRecordLoaded(event) {
        const {records} = event.detail;
        const recordData = records[this.recordId];
        this.carName = getFieldValue(recordData,Name_Field);
        this.carPictureURL= getFieldValue(recordData,Picture_URL_Field);

    }
    connectedCallback() {
        this.subscribeHandler();
    }
    subscribeHandler(){
        this.carSelectionSubscription = subscribe(this.messageContext,CARS_SELECTED_MESSAGE,(message)=>this.handleCarSelected(message));
    }
    handleCarSelected(message){
        this.recordId = message.carId;
    }
    disconnectedCallback() {
        unsubscribe(this.carSelectionSubscription);
        this.carSelectionSubscription = null;
    }
    handleNavigationToRecordPage(){
        this[NavigationMixin.Navigate]({
            type:'standard__recordPage',
            attributes:{
                recordId : this.recordId,
                objectApiName: CAR_OBJECT.objectApiName,
                actionName:'view'
            }
        })
    }
}
				
			
carCard.css
				
					section{
	font-weight: bold;
	font-size: 0.85rem;
	margin-top: 0.75rem;
	text-transform: uppercase;
	background: #ecebea;
	border-radius: 5px;
	padding: 0.25rem;
}
				
			
carCard.js-meta.xml
				
					<?xml version="1.0"?>
<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata">
	<apiVersion>57.0</apiVersion>
	<isExposed>true</isExposed>
	<masterLabel>Car Card</masterLabel>
	<targets>
		<target>lightning__AppPage</target>
	</targets>
</LightningComponentBundle>
				
			

Go to Lightning App Builder and create an App Page, “Car Explorer” and add the components “carFilter”, “carTileList” and “carCard” in theĀ  page and click on Save.

Go to App Manager , create a new lightning app “CAR_HUB“. Add the app page “Car Explorer” and Car object in the navigation items.

Go to App Launcher and Search for “CAR_HUB“. Test the functionality.

Article Information