Salesforce Asked on October 4, 2021
I need to show list of cases retreived. Once the list is visible, there are two things i need to do with css that i am struggling with –
Here is a sample picture that shows the desired result. There is an item that is clicked on, and there is an item that has mouse hove (blue boundary)
As far as implementation goes, i have a parent component – maMyCasesListView, and a child component maCaseListItem
Parent component’s job is to get list of cases from server. Then iterate over them. In each iteration, it passes the case to child component, which then displays the relevant details.
Parent component code maMyCasesListView
HTML
<template>
<div class="container slds-p-around_large slds-scrollable_y">
<div class="slds-text-title_caps slds-text-title_bold slds-p-bottom_medium">My Cases</div>
<div>
<template if:true={cases.data}>
<lightning-layout class="slds-grid slds-grid_vertical" horizontal-align="left">
<template for:each={cases.data} for:item="currentcase">
<c-ma-case-list-item
class="slds-p-top_medium slds-p-bottom_medium"
key={currentcase.Id}
macase={currentcase}
onselect={handleSelect}
></c-ma-case-list-item>
</template>
</lightning-layout>
</template>
</div>
</div>
</template>
Javascript
import { LightningElement, wire } from 'lwc';
import getCaseList from '@salesforce/apex/MA_CasesStore.getCaseList';
export default class MaMyCasesListView extends LightningElement {
selectedcase;
@wire(getCaseList) cases;
handleSelect(event) {
const caseId = event.detail;
this.selectedcase = this.cases.data.find(
(macase) => macase.Id === caseId
);
const selectEvent = new CustomEvent('caseselect', {
detail: caseId
});
// Fire the custom event
this.dispatchEvent(selectEvent);
}
}
Code of child component-
HTML
<template>
<div onclick={handleClick}>
<lightning-layout horizontal-align="left" class="slds-grid slds-grid_vertical slds-text-align--left">
<lightning-layout-item horizontal-align="left" class="slds-text-align--left">
<b>{macase.Subject}</b>
</lightning-layout-item>
<lightning-layout-item class="slds-text-align--left slds-m-top_small">
<lightning-layout>
<lightning-layout-item horizontal-align="left" size="4">{macase.Status}</lightning-layout-item>
<lightning-layout-item horizontal-align="right">{macase.CaseNumber}</lightning-layout-item>
</lightning-layout>
</lightning-layout-item>
</lightning-layout>
</div>
</template>
Javascript
import { LightningElement, api } from 'lwc';
export default class MaCaseListItem extends LightningElement {
@api macase;
handleClick(event) {
const selectEvent = new CustomEvent('select', {
detail: this.macase.Id
});
// Fire the custom event
this.dispatchEvent(selectEvent);
}
}
Since Rahul's answer didn't address the border on mouse hover (and I was working on this anyway), I'm going to give you a second answer.
Key points:
selected
property to true
on the selected child componenttrue
and B) all others have that property set to false
.slds-theme_inverse
or slds-theme_alt-inverse
to easily give your div a dark background and white text (as long as you like the colors Salesforce chose)border: 2px solid #1589ee;
, probably (#1589ee
is defined as Salesforce's brand border color in Lightning Design System)border: 2px solid transparent;
Here's a Playground Link with a working prototype.
And here's another updated version of your code:
Parent HTML
<template>
<div class="container slds-p-around_large slds-scrollable_y slds-theme_shade">
<div class="slds-text-title_caps slds-text-title_bold slds-p-bottom_medium">
My Cases
</div>
<div>
<template if:true={cases.data}>
<lightning-layout
class="slds-grid slds-grid_vertical"
horizontal-align="left"
>
<template for:each={cases.data} for:item="currentcase">
<c-ma-case-list-item
data-id={currentcase.Id}
key={currentcase.Id}
macase={currentcase}
onselect={handleSelect}
onmouseover={handleMouseover}
onmouseout={handleMouseout}
></c-ma-case-list-item>
</template>
</lightning-layout>
</template>
</div>
</div>
</template>
Parent JS:
import { LightningElement, track, wire } from 'lwc';
import getCaseList from '@salesforce/apex/MA_CasesStore.getCaseList';
export default class MaMyCasesListView extends LightningElement {
selectedCase;
@wire(getCaseList) cases;
handleSelect(event) {
let caseId = event.detail;
this.selectedCase = this.cases.data.find(c => c.Id === caseId);
this.toggleListItems('selected', caseId);
}
handleMouseover(event) {
this.toggleListItems('mouseIsOver', event.target.dataset.id);
}
handleMouseout(event) {
event.target.mouseIsOver = false;
}
toggleListItems(property, caseId) {
this.template.querySelectorAll('c-ma-case-list-item').forEach(item => {
if (item.macase.Id === caseId) {
item[property] = true;
} else {
item[property] = false;
}
});
}
}
Child HTML
<template>
<div
class={divClass}
onclick={handleClick}
>
<lightning-layout
horizontal-align="left"
class="slds-grid slds-grid_vertical slds-text-align--left"
>
<lightning-layout-item class="slds-text-align--left">
<b>{macase.Subject}</b>
</lightning-layout-item>
<lightning-layout-item class="slds-text-align--left slds-m-top_x-small">
<lightning-layout>
<lightning-layout-item size="4">
{macase.Status}
</lightning-layout-item>
<lightning-layout-item>
{macase.CaseNumber}
</lightning-layout-item>
</lightning-layout>
</lightning-layout-item>
</lightning-layout>
</div>
</template>
Child JS
import { LightningElement, api } from 'lwc';
export default class MaCaseListItem extends LightningElement {
@api macase;
@api selected;
@api mouseIsOver;
handleClick(event) {
this.dispatchEvent(new CustomEvent('select', {
detail: this.macase.Id
}));
}
get divClass() {
let cls = 'slds-p-around_small'
if (this.selected) {
cls += ' slds-theme_inverse';
}
if (this.mouseIsOver) {
cls += ' c-mouseover-border'
}
return cls;
}
}
Child CSS
div {
border: 2px solid transparent;
}
.c-mouseover-border {
border: 2px solid #1589ee;
}
Correct answer by Matthew Souther on October 4, 2021
We use the event to send data from child to parent. Public attribute to send data from parent to child. Looks like you are trying to fire an event from parent to child which does not work.
Instead,
select
event handler, you need to iterate all cases and set the selected attribute of the particular selected case. And that's it.Here is the code.
Define a public property to hold the selected attribute.
@api selected = false;
handleClick(event) {
const selectEvent = new CustomEvent('select', {
detail: this.macase.Id
});
// Fire the custom event
this.dispatchEvent(selectEvent);
}
// Set the background color class if this attribute is true.
get selectedClass(){
return this.selected ? 'slds-theme_alt-inverse' : ''; // you can use your custom class here.
}
Note how I have set the dynamic class to the div on line to.
<template>
<div onclick={handleClick} class={selectedClass}>
<lightning-layout class="slds-grid slds-grid_vertical slds-text-align--left">
<lightning-layout-item class="slds-text-align--left">
<b>{macase.Subject}</b>
</lightning-layout-item>
<lightning-layout-item class="slds-text-align--left slds-m-top_small">
<lightning-layout>
<lightning-layout-item size="4">{macase.Status}</lightning-layout-item>
<lightning-layout-item>{macase.CaseNumber}</lightning-layout-item>
</lightning-layout>
</lightning-layout-item>
</lightning-layout>
</div>
</template>
Now mark the selected cases when event is fired from the child.
handleSelect(event) {
const caseId = event.detail;
this.cases.forEach(mycase => {
if (mycase.Id === caseId) {
mycase.selected = true;
} else {
mycase.selected = false;
}
});
}
Note: As we are directly making changes to the wired result, you will need to deep clone it using
this.cases = JSON.parse(JSON.stringify(data));
. Also, you will need to use wired function instead of property.
Answered by Rahul Gawale on October 4, 2021
Get help from others!
Recent Answers
Recent Questions
© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP