Trying to figure out a way of getting the expandable section below the main row - expand to be full width of the table. I am having issues with it just fitting within the first column.
Are there alternatives? First I wanted to make a slide in Panel once you click a link … that didn't work. Then I tried a panel with a toggle... that didn't work.
Any and all help will be appreciated.
LWC main component
<template>
<div class="slds-tabs_default__content slds-show slds-clearfix" style="background-color:#f3f3f3;border: 1px solid; border-color: #C9C9C9; border-radius: var(--br-md);padding: var(--su12);">
<!-- <div class="slds-button-group slds-clearfix" role="group">
<lightning-button style="margin:7px;" variant="brand" label="Service GHP" title="Submit Chnages" onclick={onSGHP} class="slds-m-around_x-large"></lightning-button>
<lightning-button style="margin:7px;" variant="brand" label="Sales Motion" title="Submit Chnages" onclick={onSM} class="slds-m-around_x-large"></lightning-button>
<lightning-button style="margin:7px;" variant="brand" label="Implementation GHP" title="Submit Chnages" onclick={onIGHP} class="slds-m-around_x-large"></lightning-button>
</div> -->
<div class="slds-card slds-page-header" style="border: 0;
box-shadow: none;
border-radius: var(--lwc-borderRadiusMedium,0.25rem)!important;">
<div class="" style="background-color: #f3f3f3; display: flex;
font-size: var(--slds-c-card-heading-font-size, var(--sds-c-card-heading-font-size, var(--lwc-varFontSize5,1rem)));
font-weight: var(--slds-c-card-heading-font-weight, var(--sds-c-card-heading-font-weight, var(--lwc-cardFontWeight,700)));
line-height: var(--lwc-lineHeightHeading,1.25); float: left!important;
margin-bottom: 10px;
padding-top: 17px;
padding-left: 20px; ">
Risk Event Tasks
</div>
<div style="float:right!important; margin-bottom: 10px; padding-top:10px; padding-right:10px;">
<lightning-button variant="brand-outline" onclick={addTask} label="New Task" aria-haspopup="modal">
</lightning-button>
</div>
</div>
<table style="border: 1px solid; border-color: #C9C9C9; border-radius: var(--br-md);padding: var(--su12);"
class="table-dragable slds-table slds-table_cell-buffer slds-table slds-table_cell-buffer slds-table_bordered slds-table_col-bordered slds-max-medium-table_stacked-horizontal" aria-describedby="User Details">
<thead>
<tr class="slds-line-height_reset">
<th scope="col" style="max-width:175px;">Name</th>
<th scope="col" style="max-width:50px;">Task #</th>
<th scope="col" style="width:20px;display: none;">ID</th>
<th scope="col" style="max-width:175px;">Task</th>
<th scope="col" style="max-width:125px;">Phase</th>
<th scope="col" style="max-width:100px;">Status</th>
<th scope="col" >Started Date</th>
<th scope="col" >Last Touched</th>
<th scope="col" >Closed Date</th>
</tr>
</thead>
<tbody>
<template if:true={tasklist}>
<template for:each={tasklist} for:item="task" for:index="index">
<tr class="grabable"
key={task.Id}
id={task.Id}
draggable="true"
data-drag-id={task.Task__c}
ondragstart={onDragStart} ondragover={onDragOver} ondrop={onDrop}>
<!-- THIS IS WHERE THE CODE I NEED FIXED STARTS-->
<th scope="col" style="max-width:175px;">
{task.Name}
<template for:each={sections} for:item="section">
<c-expandable-section key={section.id} id={section.id} label="more details">
<c-client-health-task-add-new></c-client-health-task-add-new>
</c-expandable-section>
</template>
</th>
<!-- THIS IS WHERE THE CODE I NEED FIXED ENDS-->
<th scope="col" class="myIndex">{task.Task__c}</th>
<th scope="col" class="myId" style="display: none;">{task.Id}</th>
<th scope="col" class="slds-cell-wrap" style="max-width:175px;">{task.Task_Name__c}</th>
<th scope="col" class="myPhase slds-cell-wrap">{task.Phase__c}</th>
<th scope="col">{task.Task_Status__c}</th>
<th scope="col"><lightning-formatted-date-time
value={task.Started_Date__c}
year="numeric"
month="numeric"
day="numeric"
time-zone="UTC"
></lightning-formatted-date-time></th>
<th scope="col"><lightning-formatted-date-time
value={task.Last_Touched__c}
year="numeric"
month="numeric"
day="numeric"
time-zone="UTC"
></lightning-formatted-date-time></th>
<th scope="col"><lightning-formatted-date-time
value={task.Closed_Date__c}
year="numeric"
month="numeric"
day="numeric"
time-zone="UTC"
></lightning-formatted-date-time></th>
<template for:each={sections} for:item="section">
<c-expandable-section key={section.id} id={section.id} label="more details">
<c-client-health-task-add-new></c-client-health-task-add-new>
</c-expandable-section>
</template>
</tr>
</template>
</template>
<template if:true={TaskData.error}>No rows found.</template>
</tbody>
</table>
</div>
<br/>
<br/>
</template>
LWC expandable component HTML (the LWC that is inside the main LWC)
<template>
<div class="slds-section slds-is-closed" data-id={id}>
<!--section header-->
<h3 class="slds-section__title" style="bg-color: #FFF;">
<button type="button" aria-controls={id} class="slds-button slds-section__title-action" data-buttonid={id}
onclick={toggleSection}>
<lightning-icon icon-name="utility:switch" alternative-text="button icon" size="x-small"
class="slds-section__title-action-icon slds-button__icon_left"></lightning-icon>
<span class="slds-truncate" title={label}>{label}</span>
</button>
</h3>
<!--section body-->
<div class="slds-section__content">
<slot></slot>
</div>
</div>
</template>
LWC expandable component JS
import { LightningElement, api } from 'lwc';
export default class ExpandableSection extends LightningElement {
@api id;
@api label;
toggleSection(event) {
let buttonid = event.currentTarget.dataset.buttonid;
let currentsection = this.template.querySelector('[data-id="' + buttonid + '"]');
if (currentsection.className.search('slds-is-open') == -1) {
currentsection.className = 'slds-section slds-is-open';
} else {
currentsection.className = 'slds-section slds-is-close';
}
}
}
** UPDATE ** Here's the latest code change according to the solution provided.
<tbody>
<template if:true={tasklist}>
<template for:each={tasklist} for:item="task" for:index="index">
<tr class="grabable slds-hint-parent"
key={task.Id}
id={task.Id}
draggable="true"
data-drag-id={task.Task__c}
ondragstart={onDragStart} ondragover={onDragOver} ondrop={onDrop}>
<!-- <th scope="col" style="max-width:175px;">
{task.Name}
<template for:each={sections} for:item="section">
<c-expandable-section key={section.id} id={section.id} label="more details">
<c-client-health-task-add-new></c-client-health-task-add-new>
</c-expandable-section>
</template>
</th> -->
<th
scope="row"
class="expand-column"
>
{task.Name}
<lightning-button-icon
class="slds-var-p-horizontal_x-small"
variant="bare"
size="large"
icon-name={task.iconName}
alternative-text="Expand"
data-id={task.Id}
onclick={handleExpand}
title="Expand"
>
<label>Expand</label>
</lightning-button-icon>
</th>
<th scope="col" class="myIndex">{task.Task__c}</th>
<th scope="col" class="myId" style="display: none;">{task.Id}</th>
<th scope="col" class="slds-cell-wrap" style="max-width:175px;">{task.Task_Name__c}</th>
<th scope="col" class="myPhase slds-cell-wrap">{task.Phase__c}</th>
<th scope="col">{task.Task_Status__c}</th>
<th scope="col"><lightning-formatted-date-time
value={task.Started_Date__c}
year="numeric"
month="numeric"
day="numeric"
time-zone="UTC"
></lightning-formatted-date-time></th>
<th scope="col"><lightning-formatted-date-time
value={task.Last_Touched__c}
year="numeric"
month="numeric"
day="numeric"
time-zone="UTC"
></lightning-formatted-date-time></th>
<th scope="col"><lightning-formatted-date-time
value={task.Closed_Date__c}
year="numeric"
month="numeric"
day="numeric"
time-zone="UTC"
></lightning-formatted-date-time></th>
<!-- <template for:each={sections} for:item="section">
<c-expandable-section key={section.id} id={section.id} label="more details">
<c-client-health-task-add-new></c-client-health-task-add-new>
</c-expandable-section>
</template> -->
</tr>
<tr key={task.Id} if:true={task.isExpanded} class="slds-hint-parent">
<th colspan="4">
<template for:each={sections} for:item="section">
<c-expandable-section key={section.id} id={section.id} label="more details">
<c-client-health-task-add-new></c-client-health-task-add-new>
</c-expandable-section>
</template>
</th>
</tr>
</template>
</template>
<template if:true={TaskData.error}>No rows found.</template>
</tbody>
This is the entire JS file:
import { LightningElement, wire, track, api } from "lwc";
import MyModalAddNew from 'c/clientHealthTaskAddNew';
import MyModalEdit from 'c/clientHealthTaskEdit';
import getList from '@salesforce/apex/ASI_RiskEventTaskController.getRiskEventTask';
import saveList from '@salesforce/apex/ASI_RiskEventTaskController.saveRiskEventTask';
import { updateRecord } from 'lightning/uiRecordApi';
import { refreshApex } from "@salesforce/apex";
export default class DataTableDragable extends LightningElement {
@api recordId;
@api userMap;
@api dragMap;
users;
tasklist;
error;
testId = 'a3Z8K000001fO7BUAU';
handleExpand(event) {
let taskId = event.target.dataset.id;
let taskFound = this.tasklist.find((task) => task.Id === taskId);
// toggle the value
taskFound.isExpanded = !taskFound.isExpanded;
// set the icon name
taskFound.iconName = taskFound.isExpanded
? "utility:chevrondown"
: "utility:chevronright";
}
@track TaskData = JSON.parse('{"getTaskData": [{"Id": "111", "Phase": "Notification", "Task": "Client contacted & Meeting confirmed","Checklist": "Lorem ipsum dolor sit amet. Sit illo voluptas et fugit quibusdam qui omnis","index": 1},{"Id": "222","Phase": "Discovery", "Task": "Gather and document internal facts/history","Checklist": "Lorem ipsum dolor sit amet. Sit illo voluptas et fugit quibusdam qui omnis","index": 2},{"Id": "333","Phase": "Creation", "Task": "M and A Paperwork/Proposal created/sent to customer","Checklist": "Qui doloremque dolorem ut aperiam impedit et quidem praesentium","index": 3},{"Id": "444","Phase": "Present/Accept", "Task": "Proposal Presented","Checklist": "Ab internos consectetur aut soluta velit ut rerum quia","index": 4},{"Id": "555","Phase": "Delivery", "Task": "N/A","Checklist": "A consequuntur quaerat ea dolor necessitatibus rem voluptas modi quo expedita deleniti ea sunt facilis non modi","index": 5},{"Id": "666","Phase": "Post Plan Governance", "Task": "Update Client Health/Close Risk","Checklist": "Qui doloremque dolorem ut aperiam impedit et quidem praesentium","index": 6}]}');
@wire(getList, { retId: '$testId'}) //a3Z8K000001bxakUAA
contactRec(result)
{
this.taskResult = result;
if(result.error){
console.log('error is#'+result.error);
this.error = result.error;
}
else if(result.data){
this.tasklist = result.data;
}
}
async addTask() {
const result = await MyModalAddNew.open({
size: 'small',
description: 'Accessible description of modal\'s purpose',
content: 'Risk Event Task',
});
console.log(result);
refreshApex(this.taskResult)
.then(result => this.processRowNumbers())
.catch(error => console.log('adTask: ' + error));
}
async editTask() {
const result = await MyModalEdit.open({
size: 'small',
description: 'Accessible description of modal\'s purpose',
content: 'Edit Risk Event Task',
});
console.log(result);
refreshApex(this.taskResult)
.then(result => this.processRowNumbers())
.catch(error => console.log('adTask: ' + error));
}
updateRecordView(recordId) {
updateRecord({fields: { Id: recordId }});
this.updateRecordView(this.recordId);
}
// //Boolean tracked variable to indicate if modal is open or not default value is false as modal is closed when page is loaded
// @track isModalOpen = false;
// openModal() {
// // to open modal set isModalOpen tarck value as true
// this.isModalOpen = true;
// }
// closeModal() {
// // to close modal set isModalOpen tarck value as false
// this.isModalOpen = false;
// }
// submitDetails() {
// // to close modal set isModalOpen tarck value as false
// //Add your code to call apex method or do some processing
// this.isModalOpen = false;
// }
renderedCallback() {
if (!!this.tasklist) {
this.userMap = new Map();
let tempArray = JSON.parse(JSON.stringify(this.tasklist));
tempArray.forEach((arrayElement, index) => {
//arrayElement.index = index;
this.userMap.set(arrayElement.Id, arrayElement);
});
console.log(
": ------------------------------------------------------------"
);
console.log(
"DataTableDragable -> renderedCallback -> tempArray",
JSON.stringify(tempArray)
);
console.log(
": ------------------------------------------------------------"
);
this.users = JSON.parse(JSON.stringify(tempArray));
}
}
// handleSubmit() {
// console.log("in submit method");
// let data = this.users.data;
// console.log(": ----------------------------------------------");
// console.log(
// "DataTableDragable -> handleSubmit -> data",
// JSON.stringify(data)
// );
// console.log(": ----------------------------------------------");
// }
processRowNumbers() {
console.log('PRN');
const trs = this.template.querySelectorAll(".myIndex");
const ids = this.template.querySelectorAll(".myId");
for (let i = 0; i < trs.length; i++) {
let currentRowId = ids[i].innerText;
let currentRowRef = this.userMap.get(currentRowId);
currentRowRef.Task__c = i + 1;
this.userMap.set(currentRowId, currentRowRef);
trs[i].innerText = i + 1;
}
this.users = Array.from(this.userMap.values());
this.tasklist = Array.from(this.userMap.values());
let data = this.users;
console.log(": ----------------------------------------------");
console.log(
"DataTableDragable -> handleSubmit -> data",
JSON.stringify(data)
);
console.log(": ----------------------------------------------");
saveList({ retl: this.tasklist })
.then((result) => {
console.log(result);
this.error = undefined;
})
.catch((error) => {
console.log(error);
this.error = error;
});
}
onDragStart(evt) {
const inputs = this.template.querySelectorAll(".mychkbox");
this.dragMap = new Map();
if (inputs) {
for (let i = 0; i < inputs.length; i++) {
if (inputs[i].checked) {
let currentRow = inputs[i].parentNode.parentNode;
let currentDragId = currentRow.dataset.dragId;
this.dragMap.set(currentDragId, currentRow);
//currentRow.classList.add("grabbed");
}
}
}
let eventRowDataId = evt.currentTarget.dataset.dragId;
evt.dataTransfer.setData("dragId", eventRowDataId);
evt.dataTransfer.setData("sy", evt.pageY);
evt.dataTransfer.effectAllowed = "move";
evt.currentTarget.classList.add("grabbed");
if (this.dragMap.has(eventRowDataId)) {
this.dragMap.forEach((value) => value.classList.add("grabbed"));
}
}
onDragOver(evt) {
evt.preventDefault();
evt.dataTransfer.dropEffect = "move";
}
onDrop(evt) {
evt.preventDefault();
let sourceId = evt.dataTransfer.getData("dragId");
const sy = evt.dataTransfer.getData("sy");
const cy = evt.pageY;
if (sy > cy) {
if (this.dragMap.has(sourceId)) {
Array.from(this.dragMap).reverse().forEach( element => {
let key = element[0];
const elm = this.template.querySelector(`[data-drag-id="${key}"]`);
if (!!elm) {
elm.classList.remove("grabbed");
}
evt.currentTarget.parentElement.insertBefore(elm, evt.currentTarget);
});
} else {
const elm = this.template.querySelector(`[data-drag-id="${sourceId}"]`);
if (!!elm) {
elm.classList.remove("grabbed");
}
evt.currentTarget.parentElement.insertBefore(elm, evt.currentTarget);
}
} else {
if (this.dragMap.has(sourceId)) {
this.dragMap.forEach((value, key, map) => {
const elm = this.template.querySelector(`[data-drag-id="${key}"]`);
if (!!elm) {
elm.classList.remove("grabbed");
}
evt.currentTarget.parentElement.insertBefore(
elm,
evt.currentTarget.nextElementSibling
);
});
} else {
const elm = this.template.querySelector(`[data-drag-id="${sourceId}"]`);
if (!!elm) {
elm.classList.remove("grabbed");
}
evt.currentTarget.parentElement.insertBefore(
elm,
evt.currentTarget.nextElementSibling
);
}
}
this.processRowNumbers();
}
onRefresh() {
this.dispatchEvent(new RefreshEvent());
console.log('Refresh Event');
}
onSGHP() {
this.testId = 'a3Z8K000001fO7BUAU';
}
onSM() {
this.testId = 'a3Z8K000001fO76UAE';
}
onIGHP() {
this.testId = 'a3Z8K000001fO7BUAU';
}
}