3

I am trying to parse a JSON string from one of the fields on a record within JS and trying to display the array of items on my lightning-datatable. I am using LWC for this implementation.

JSON string:

{"students" : 
  [
    {
    "studId" : "089180000AA0091",
    "classRank": "43",
    "topped": "Biology",
    "gradeCode":"CURIOUS",
    "subjCode":"989877788" 
    },

    {
    "studId" : "089180000AA0092",
    "classRank": "44",
    "topped": "Biology",
    "gradeCode":"SCORER",
    "subjCode":"989877788"  
    }
  ]
}

LWC's JS:

childRecords = [];
toDisplay = [];
connectedCallback() {
    this.data = '';
    this.parseData = [];
    this.childRecords = [];
    this.toDisplay = [];
    getJsonString({myId:this.recordId})
    .then(result => {
        this.data= result;
        this.parseData = JSON.parse(this.data);
        this.parseData.students.forEach( recItem =>{
            console.log(recItem.studId);
            console.log(recItem.classRank);
            console.log(recItem.topped);
            this.childRecords.push(recItem);
        });
        this.childRecords.forEach(student=>{
            this.toDisplay.push(JSON.stringfy(student));
        });
    })
    .catch(error => {
        console.log('Errored out.');
    });
}

HTML

<lightning-datatable key-field="studId" data={toDisplay} columns={studColumn} 
        hide-checkbox-column data-id="student">
 </lightning-datatable>

So, here is the Columns I have right now.

const COLUMNS = [
{ label: 'StudentID', initialWidth: 180, fieldName: 'studId', type: 'text', sortable : false, wrapText: true }, 
{ label: 'Class Rank', initialWidth: 300, fieldName: 'classRank', type:'text', sortable : true ,wrapText: true, hideDefaultActions: true},  
{ label: 'Topped',initialWidth: 150, fieldName: 'topped', type:'text', hideDefaultActions: true},   
{ label: 'Grade Code',initialWidth: 155, fieldName: 'gradeCode', type:'text', wrapText: true, hideDefaultActions: true}
];

I would like to somehow wire the values I get from my parsed JSON to set the value for fieldName. If there is any better way then this approach, I would like to try it out.

6
  • Hi, are you getting values when you are consoling in for loop? May 28 at 9:09
  • Hi @ShagunSharma, Yes, I am getting the values in the console. I just updated my above code. My bad, I was trying not to post any of my actual code and missed to include the students object while iterating. May 28 at 21:40
  • Hi @ShagunSharma that suggestion didn't work well. If you have any better approach or a workable solution, please feel to provide it. Jun 1 at 14:43
  • Hi, are you declaring your variables in the class body? I can't see the declarations anywhere. Jun 1 at 18:54
  • Why do you need to change fieldName dynamically? Won't the payload structure always be the same?
    – Adrian Larson
    Jun 1 at 19:07
3
+50

You need to track your toDisplay array properly.

LWC can track scalar values like strings and integers automatically, but it can't track values INSIDE an array.

Add:

@track toDisplay = [];

OR, try assigning an whole new array to toDisplay. Create a temporary array, add all your items to that and then assign that to toDisplay when you are done with the forEach loop.

I recommend going with the second option, because you will avoid triggering a rerender cycle each time you add an item to the array.

FINALLY you are re-encoding the result as a string again - the datatable needs an array, not a string as it's datasource.

I think you will need something like this:

getJsonString({myId:this.recordId})
.then(result => {
    this.data = result;
    this.parseData = JSON.parse(this.data);
    this.toDisplay = this.parseData.students;
})
.catch(error => {
    console.log('Errored out.');
});

Notice no loop necessary - all the data is already in the correct format.

This ALL depends on the data flow. Are you receiving a JSON string for you Apex call result?

IF a string, the dataflow is this:

Call Apex -> recieve JSON string -> parse to Javascript Object -> Extract array -> Assign this array to the datatable.

IF you are getting actual array from the Apex method, then the dataflow is this:

Call Apex -> recieve Javascript Object -> Extract array -> Assign this array to the datatable.
2
  • Hi Caspar, thanks for the detailed answer. It's hard to get good resources to understand the logic (at least for a newbie like me). Thank you for putting together a great answer. Jun 1 at 19:56
  • Yes, it is definitely hard to get started - esp to work out what the component SHOULD be doing and how it should do that in a conceptual sense :) Jun 1 at 20:07
1

I am updating the code below:

JS :

    studColumn = COLUMNS
    @track toDisplay = [];

    connectedCallback() {
        getJsonString({myId:this.recordId})
            .then(result => {
                console.log(result);
                var parseData = JSON.parse(result);
                this.toDisplay=parseData.students;
                console.log(JSON.stringify(this.toDisplay));
            })
            .catch(error => {
                console.log('Errored out.');
            });
    }

HTML :

        <lightning-datatable key-field="studId" data={toDisplay} columns={studColumn} 
        hide-checkbox-column data-id="student">
        </lightning-datatable>
7
  • Hi, if I console the value of this.toDisplay after the for loop, I am getting it as [object Object],[object Object]. Also, I am getting nothing to display on my Lightning-datatable. Jun 1 at 15:43
  • I have updated the js I tried, please have a look Jun 1 at 15:58
  • What are you getting for the values within this.parseData.students.forEach(recItem => as I can see all JSON values. But, for this.childRecords.push(recItem);, it's storing [Object object]. And the same is being iterated within this.childRecords.forEach(student =>. BTW, I am fetching the JSON string from a field value of the record. Jun 1 at 16:07
  • i.stack.imgur.com/cz18h.gif I am getting something like this Jun 1 at 17:10
  • 1
    @AustinEvans I have updated both the JS and HTML above. I have removed all the extra variables and for loops. I hope this works for you. Jun 1 at 18:29

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.