I have created a Custom Inline editable table in LWC. Here are the details:
Apex Class : I am getting the fields to be displayed from Field set and created one wrapper class to pass the fields details to LWC.
LWC : I have created two LWC ( one is parent to iterate through available fields and record set and pass the details to child and child component displaying fields based upon datatype).
The main problem is Aura Component supports two way binding i.e. when you make some changes on parent attribute the same will be reflecting in child if the attribute is binded and vice versa, whereas LWC only supports one way binding. So in my case if i am making any changes on the input fields ( available on child component ) it's not getting reflected to the parent. As per the LWC documentation it seems Custom Event is the only way to pass the details. I have to pass multiple details like field API Name and selected/entered value but event has only one param to pass infos. Do we have any other way to resolve the issue?
Here is my Wrapper class:
public class FieldWrapperClass{
@AuraEnabled public String FieldLabel{get;set;}
@AuraEnabled public String FieldAPI{get;set;}
@AuraEnabled public Boolean isEditable{get;set;}
@AuraEnabled public String fieldType{get;set;}
@AuraEnabled public List options{get;set;}
}
public class OptionWrapper{
@AuraEnabled public String label{get;set;}
@AuraEnabled public String value{get;set;}
}
LWC Parent Component
:
<table class="slds-table slds-table_bordered slds-table_cell-buffer slds-table_col-bordered slds-no-row-hover ">
<thead>
<tr class="slds-text-title_caps">
<template for:each={fieldList} for:item="fieldObj">
<th scope="col" key={fieldObj.FieldAPI} class="slds-cell-wrap">
<div class="slds-cell-wrap" title={fieldObj.FieldLabel}>
{fieldObj.FieldLabel}
</div>
</th>
</template>
</tr>
</thead>
<tbody>
<template for:each={paginatedMOs} for:item="moObj">
<tr key={moObj.Id}>
<template for:each={fieldList} for:item="fieldObj">
<td class="slds-cell-wrap" key={fieldObj.FieldAPI}>
<c-child-row sobject={moObj} field={fieldObj}></c-child-row>
</td>
</template>
</tr>
</template>
</tbody>
Child LWC
<div if:true={isstring}>
<lightning-formatted-rich-text value={cellvalue}></lightning-formatted-rich-text>
<!--<p><lightning-formatted-text value={cellvalue}></lightning-formatted-text></p>-->
</div>
<div if:true={isdate}>
<p><lightning-formatted-date-time value={cellvalue}
year="numeric"
month="numeric"
day="numeric"
time-zone-name="short">
</lightning-formatted-date-time>
</p>
</div>
<div if:true={isreference}>
<p><lightning-formatted-text value={cellvalue}></lightning-formatted-text></p>
</div>
<div if:true={isdouble}>
<p><lightning-formatted-number value={cellvalue}></lightning-formatted-number></p>
</div>
<div if:true={iscurrency}>
<p><lightning-formatted-text value={cellvalue}></lightning-formatted-text></p>
</div>
<div if:true={istextarea}>
<p><lightning-formatted-text value={cellvalue}></lightning-formatted-text></p>
</div>
<div if:true={isboolean}>
<!-- <lightning-input type="checkbox" label="" name="input1" value={cellvalue} " ></lightning-input> -->
<lightning-input disabled type="checkbox" label="" name="input1" value={cellvalue} ></lightning-input >
</div>
<div if:true={ispicklist}>
<p><lightning-formatted-text value={cellvalue}></lightning-formatted-text></p>
</div>
</div>
<div if:true={field.isEditable}>
<div if:true={ispicklist}>
<div class="picklistClass"><lightning-combobox name="progress"
label=""
value={cellvalue}
options={selectOptions}
onchange={onValueSelection}></lightning-combobox></div>
</div>
<div if:true={isboolean}>
<lightning-input type="checkbox" label="" name="input1" value={cellvalue}></lightning-input>
</div>
<div if:true={istextarea}>
<div class="picklistClass"><lightning-textarea name="input3" label="" value={cellvalue}></lightning-textarea></div>
</div>
</div>
JS
connectedCallback() {
let fldType = this.field.fieldType;
this.isstring = fldType === 'STRING'? true : false;
this.isreference = fldType === 'REFERENCE'? true : false;
this.isdate = fldType === 'DATE'? true : false;
this.isdouble = fldType === 'DOUBLE'? true : false;
this.iscurrency = fldType === 'CURRENCY'? true : false;
this.istextarea = fldType === 'TEXTAREA'? true : false;
this.isboolean = fldType === 'BOOLEAN'? true : false;
this.ispicklist = fldType === 'PICKLIST'? true : false;
if(fldType === 'PICKLIST') {
for(const list of this.field.options){
const option = {
label: list.label,
value: list.value
};
this.selectOptions = [ ...this.selectOptions, option ];
}
}
this.cellvalue = this.sobject[this.field.FieldAPI];
}
onValueSelection(event){
this.cellvalue = event.target.value;
}
}
===
returns true or false, so you don't need to use ternary operators:this.isstring = fldType === 'STRING';