title: LWC Related List Inline Editing with Dynamic Columns
body: <p>I hope you can help. I'm wanting to create a LWC that uses the Datatable component with Inline Editing. but which get's the columns to display from the Lightning Page Parameters in the JS.Meta file Properties. </p>
  
  <p>For instance, the Properties will have a field for inputting the fields we want to display in the related list in a comma deliminated fashion, and the passes these fields into the component / a dynamic piece of soql to be used in the Edtiable List. </p>
  
  <p>All of the examples i have found have statically declared columns like below. But i really want these to be defined in the Lightning Builder Page so the component can be re-used on multiple objects and with different fields etc: </p>
  
  <p><strong>Class</strong>:</p>
  
  <pre><code>public with sharing class ContactController {
  
      @AuraEnabled(cacheable=true)
      public static List&lt;Contact&gt; getContactList() {
          return [SELECT Id, FirstName, LastName, Title, Phone, Email FROM Contact LIMIT 10];
      }
  }
  </code></pre>
  
  <p><strong>HTML</strong>: </p>
  
  <pre><code>&lt;template&gt;
      &lt;lightning-card title="Datatable Example" icon-name="custom:custom63"&gt;
  
          &lt;div class="slds-m-around_medium"&gt;
              &lt;template if:true={contact.data}&gt;
                  &lt;lightning-datatable
                      key-field="Id"
                      data={contact.data}
                      columns={columns}
                      onsave={handleSave}
                      draft-values={draftValues}&gt;
                  &lt;/lightning-datatable&gt;
              &lt;/template&gt;
              &lt;template if:true={contact.error}&gt;
                  &lt;!-- handle Apex error --&gt;
              &lt;/template&gt;
          &lt;/div&gt;
      &lt;/lightning-card&gt;
  &lt;/template&gt;
  </code></pre>
  
  <p><strong>JS</strong>:</p>
  
  <pre><code>import { LightningElement, wire, track } from 'lwc';
  import getContactList from '@salesforce/apex/ContactController.getContactList';
  import { updateRecord } from 'lightning/uiRecordApi';
  import { refreshApex } from '@salesforce/apex';
  import { ShowToastEvent } from 'lightning/platformShowToastEvent';
  import FIRSTNAME_FIELD from '@salesforce/schema/Contact.FirstName';
  import LASTNAME_FIELD from '@salesforce/schema/Contact.LastName';
  import ID_FIELD from '@salesforce/schema/Contact.Id';
  
  
  const COLS = [
      { label: 'First Name', fieldName: 'FirstName', editable: true },
      { label: 'Last Name', fieldName: 'LastName', editable: true },
      { label: 'Title', fieldName: 'Title' },
      { label: 'Phone', fieldName: 'Phone', type: 'phone' },
      { label: 'Email', fieldName: 'Email', type: 'email' }
  ];
  export default class DatatableUpdateExample extends LightningElement {
  
      @track error;
      @track columns = COLS;
      @track draftValues = [];
  
      @wire(getContactList)
      contact;
  
      handleSave(event) {
  
          const fields = {};
          fields[ID_FIELD.fieldApiName] = event.detail.draftValues[0].Id;
          fields[FIRSTNAME_FIELD.fieldApiName] = event.detail.draftValues[0].FirstName;
          fields[LASTNAME_FIELD.fieldApiName] = event.detail.draftValues[0].LastName;
  
          const recordInput = {fields};
  
          updateRecord(recordInput)
          .then(() =&gt; {
              this.dispatchEvent(
                  new ShowToastEvent({
                      title: 'Success',
                      message: 'Contact updated',
                      variant: 'success'
                  })
              );
              // Clear all draft values
              this.draftValues = [];
  
              // Display fresh data in the datatable
              return refreshApex(this.contact);
          }).catch(error =&gt; {
              this.dispatchEvent(
                  new ShowToastEvent({
                      title: 'Error creating record',
                      message: error.body.message,
                      variant: 'error'
                  })
              );
          });
      }
  }
  </code></pre>
  
  <p>Ideally, i'd like to declare the Object and Fields etc in the JS-Meta file, like below. And have these pass into the class / JS etc: </p>
  
  <pre><code>&lt;?xml version="1.0" encoding="UTF-8"?&gt;  
  &lt;LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata" fqn="EditableRelatedList"&gt;  
      &lt;apiVersion&gt;45.0&lt;/apiVersion&gt;  
      &lt;isExposed&gt;true&lt;/isExposed&gt;  
      &lt;targets&gt;  
          &lt;target&gt;lightning__RecordPage&lt;/target&gt;  
      &lt;/targets&gt;  
      &lt;targetConfigs&gt;  
          &lt;!-- Component UI Properties --&gt;
          &lt;targetConfig targets="lightning__RecordPage"&gt;  
              &lt;property name="strTitle" type="String" label="Title" description="Enter the title"/&gt;  
              &lt;property name="objectName" type="String" label="Object Name" description="Enter the object name"/&gt;  
              &lt;property name="parentFieldAPIName" type="String" label="Parent Field API Name" description="Enter the parent field API Name"/&gt;  
              &lt;property name="whereClause" type="String" label="WHERE Clause" description="Enter your WHERE clause (Not Required). Do not include 'WHERE'. Eg: firstName = 'David' AND lastName != 'Bradbury'"/&gt; 
              &lt;property name="fields" type="String" label="Fields" description="Enter the API Names of the fields you would like to use in this Related List seperated by a comma. Eg: FirstName, LastName, CustomField1__c, CustomField2__c "/&gt; 
              &lt;property name="errorMessage" type="String" label="Error Message" description="Enter your Error Message for when there are 0 records"/&gt;
          &lt;/targetConfig&gt;  
      &lt;/targetConfigs&gt;  
  &lt;/LightningComponentBundle&gt;
  </code></pre>
  
  <p>Thanks in advance!!</p>