2

I have this below query . Where i am trying to display Opportunity name and products associated to it in a lightning tree-grid structure.

The issue i am facing is i am able to display opportunity name . But i am unable to display product name and family

 List < Opportunity > opps = [ SELECT Id, Name, StageName,
                ( SELECT Id, Product2.Name, Product2.Family FROM OpportunityLineItems )
                FROM Opportunity WHERE Id IN:  oppsIds];

HTML -

 <lightning-tree-grid hide-checkbox-column columns={gridColumns} data={gridData} key-field="Id">
        </lightning-tree-grid>

JS -

gridColumns = [{
        type: 'text',
        fieldName: 'Name',
        label: 'Opportunity Name'
    },
    {
        type: 'text',
        fieldName: 'StageName',
        label: 'Stage'
    },
    {
        type: 'text',
        fieldName: 'Product2.Name',
        label: 'ProductName'

    },
    {
        type: 'text',
        fieldName: 'Product2.Family',
        label: 'Product Family'

    }
    ];

wire method returning the data

 gridColumns = [{
    type: 'text',
    fieldName: 'Name',
    label: 'Opportunity Name'
},
{
    type: 'text',
    fieldName: 'StageName',
    label: 'Stage'
},
{
    type: 'text',
    fieldName: 'Product2.Name',
    label: 'Product Name'

},
{
    type: 'text',
    fieldName: 'Product2.Family',
    label: 'Product Family'

}
];
gridData
allRows
@api recordId
@wire(fetchOLIs, { contractId: '$recordId' })
olitreedata({ error, data }) {
    if ( data ) {
  
       // this.gridData = tempData;
        this.gridData = data.map((row) => {
            row = { ...row }; // copy row object
            const items = row.OpportunityLineItems; // Save items
            delete row.OpportunityLineItems; // remove from row
            row._children = items.map((item) => this.flattenObject(item)); // flatten item
            return row;
          });

    } else if ( error ) {
     


    }
}

flattenObject(object, result = {}, path = []) {
    for (const [key, value] of Object.entries(object)) {
      if (typeof value === "object") {
        flattenObject(value, result, [...path, key]);
      } else {
        result[`${path.join(".")}${path.length ? "." : ""}${key}`] = value;
      }
    }
    return result;
  }

1 Answer 1

5

The various lightning list items (e.g. treeGrid) do not automatically navigate objects. In other words, given the field name Product2.Family, treeGrid and datatable expect data that looks like this:

[ { 'Product2.Family': 'Software' } ]

But you have data that looks like this:

[ { Product2: { Family: 'Software' } } ]

You have to manually flatten those objects using a method like this:

function flattenObject(object, result = {}, path = []) {
  for (const [key, value] of Object.entries(object)) {
    if (typeof value === "object") {
      flattenObject(value, result, [...path, key]);
    } else {
      result[`${path.join(".")}${path.length ? "." : ""}${key}`] = value;
    }
  }
  return result;
}

Which you then use in your wire handler:

if (data) {
  this.allRows = data.map((row) => {
    row = { ...row }; // copy row object
    const items = row.OpportunityLineItems; // Save items
    delete row.OpportunityLineItems; // remove from row
    row._children = items.map((item) => flattenObject(item)); // flatten item
    return row;
  });
}
9
  • Hi sfdcfox.. I am getting this error .."Uncaught (in promise) ReferenceError: LWC component's @wire target property or method threw an error during value provisioning. Original error:" at line .. "result[${path.join(".")}${path.length ? "." : ""}${key}] = value;" Jun 28, 2022 at 21:00
  • i have updated my js file above Jun 28, 2022 at 21:01
  • got the issue.. forgot to add this. flattenObject inside the function Jun 28, 2022 at 21:07
  • Thank u sfdcfox.. Jun 28, 2022 at 21:07
  • @hellraizer I was actually implying the function be outside the class, see demo.
    – sfdcfox
    Jun 28, 2022 at 21:07

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .