[SalesForce] Why without the JSON.parse method, I can’t sort the data in lightning-datatable

I'd like to understand the usefulness of the method JSON.parse in the JS file of a lwc when we want to perform certain actions on a list of objects retrieved from our apex controller. I give you an example.
I have implemented the sorting functionality on a lightning datatable in a lwc. but my problem is when I don't use the JSON.parse method when I get all the data, I get an empty proxy. Here is the the output when I'm debugging:

enter image description here

But when I use the JSON.parse method when I get the data I want to sort, I get and I see all the data when I'm debugging. Here is the output for this case:

enter image description here

Can someone help me please to understand why we can't see the data without the JSON.pase method and why without the JSON.parse method it doesn't work?

here is the html template:

      <lightning-datatable key-field="Id" 
                           data={opportunities} 
                           columns={columns}  
                           onsort={updateColumnSorting} 
                           sorted-by={sortedBy} 
                           sorted-direction={sortedDirection}>
      </lightning-datatable>

the js file:

import { LightningElement ,wire,track} from 'lwc';
import getAllOpps from '@salesforce/apex/GetAllOpportunities.getAllOpps';

export default class OpportunityList extends LightningElement {
    @track columns = [
        {
            label: 'Opportunity name',
            fieldName: 'Name',
            type: 'tex',
            sortable: true
        },
        {
            label: 'Stage Name',
            fieldName: 'StageName',
            type: 'text',
            sortable: true
        },
        {
            label: 'Close date',
            fieldName: 'CloseDate',
            type: 'date',
            sortable: true
        }

    ];

    @track error;
    @track opportunities = [];
    @track sortedBy;
    @track sortedDirection = 'asc';


    @wire(getAllOpps)
    wiredOpps({error,data}) {
        if (data) {
            this.opportunities = data;
            this.error = undefined;
        } else if (error) {
            this.error = error;
            this.opportunities = undefined;
        }
    }   

    sortData(fieldName, sortDirection){

        //let data = JSON.parse(JSON.stringify(this.opportunities));
        let data = this.opportunities;
        //function to return the value stored in the field
        const key = (a) => {
            let fieldValue = a[fieldName] ? (typeof a[fieldName] === 'string' ? a[fieldName].toLowerCase() : a[fieldName]) : '';
           return fieldValue; 
        }
        let reverse = sortDirection === 'asc' ? 1: -1;

        //set sorted data to opportunities attribute
        this.opportunities = data.sort((a,b) => {
            return reverse * ((key(a) > key(b)) - (key(b) > key(a)));
        });          

    }

    updateColumnSorting(event){
        this.sortedBy = event.detail.fieldName;
        this.sortedDirection = event.detail.sortDirection;
        this.sortData(this.sortedBy,this.sortedDirection);       
    }   

}

And the apex controller:

public with sharing class GetAllOpportunities {
   @AuraEnabled(cacheable=true)
    public static List<Opportunity> getAllOpps() {

        return [SELECT Id, Name ,StageName, CloseDate FROM Opportunity Limit 10];
    }

}


Thanks in advance!

Best Answer

The behavior you are seeing is because of Salesforce feature called lightning locker.

Any object in lwc JavaScript will use the proxy object.

https://developer.salesforce.com/docs/atlas.en-us.lightning.meta/lightning/security_proxy.htm

It's a security feature that makes debugging difficult but adds additional security.

You don't need to use JSON.stringify and JSON.parse in prod .You can use it for debugging purposes.

Update

Looking into the code , it looks like lockerservice proxy is forcing the object to readonly on datatable . You should report this as a bug to salesforce .

Related Topic