0

When i execute the apex class in the Annonymous Window i get the output, but when i call the apex class in js . in the console i get

"{
    "exceptionType": "System.JSONException",
    "isUserDefinedException": false,
    "message": "Malformed JSON: Expected '{' at the beginning of object",
    "stackTrace": "(System Code)\nClass.ListViewLwcClass.filterCriteria: line 49, column 1\nClass.ListViewLwcClass.getTimeSheetApproval: line 4, column 1"
}"  Error.

In the apex class i tried putting the queryWrapper as List to solve the issue but i get Variable query doesn't exist .

Is something wrong in the apex call in js? What is wrong with the code? Please Fix it

This is the apex code

public with sharing class ListViewLwcClass {
      @AuraEnabled
      public static List<Timesheet_Approval__c> getTimeSheetApproval(String objType, String listView) {
        String res = filterCriteria(objType, listView);
    String query = 'SELECT Id, Name, Approval_Status__c, Employee__r.Name, Customer_Engagement__r.Name, Approver__r.Name, Timesheet__r.Name FROM Timesheet_Approval__c' + (res == '' ? '' : ' WHERE ' + res);

    System.debug('Res'+res);
    List&lt;Timesheet_Approval__c&gt; ta = Database.query(query);
    System.debug('Ta'+ta);
    return ta;
  }
  @AuraEnabled(cacheable=true)
  public static String getTimeSinceLastUpdate() {
      Datetime lastUpdate = [SELECT LastModifiedDate FROM Timesheet_Approval__c ORDER BY LastModifiedDate DESC LIMIT 1].LastModifiedDate;
      Long timeDiffInSeconds = (Datetime.now().getTime() - lastUpdate.getTime()) / 1000;

      if (timeDiffInSeconds &lt; 60) {
        return 'just now';
      } else if (timeDiffInSeconds &lt; 3600) {
        Integer minutes = (Integer) (timeDiffInSeconds / 60);
        return minutes + ' minute' + (minutes == 1 ? '' : 's') + ' ago';
      } else if (timeDiffInSeconds &lt; 86400) {
        Integer hours = (Integer) (timeDiffInSeconds / 3600);
        return hours + ' hour' + (hours == 1 ? '' : 's') + ' ago';
      } else {
        Integer days = (Integer) (timeDiffInSeconds / 86400);
        return days + ' day' + (days == 1 ? '' : 's') + ' ago';
      }
    }

     @AuraEnabled(cacheable=true)
public static List&lt;ListView&gt; getListViews(String objectApiName) {
    return [SELECT Id, Name, DeveloperName FROM ListView WHERE SObjectType = :objectApiName];
}

@AuraEnabled
public static String filterCriteria(String objType, String listView){
  system.debug('ObjType: '+objType+'-- listView: '+listView);

    Id listViewId = [SELECT id FROM ListView WHERE developerName = :listView AND sObjectType=:objType].id;
    String ep = System.URL.getSalesforceBaseUrl().toExternalForm() + '/services/data/v43.0/sobjects/'+objType+'/listviews/'+listViewId+'/describe';
    HttpRequest req = new HttpRequest();
    req.setMethod('GET');
    req.setHeader('Authorization','Bearer '+Userinfo.getSessionId());
    req.setEndpoint(ep);
    HttpResponse res = new Http().send(req);
    system.debug('Res body: '+res.getBody());
    queryWrapper qw = (queryWrapper)json.deserialize(res.getBody(), queryWrapper.class);

    return (qw.query.containsIgnoreCase('WHERE')?qw.query.substringAfter('WHERE'):'');

}

public class queryWrapper{
    String query{get;set;}

}

}

This is the JS code

import { LightningElement, api, wire, track } from 'lwc';
import { NavigationMixin } from 'lightning/navigation';
import getTimeSheetApproval from '@salesforce/apex/ListViewLwcClass.getTimeSheetApproval';
import minutes from '@salesforce/apex/ListViewLwcClass.getTimeSinceLastUpdate';
import getListViews from '@salesforce/apex/ListViewLwcClass.getListViews';

export default class ListView extends NavigationMixin(LightningElement) { @track approvals = []; @track minutesSinceLastUpdate; @track isResizing = false; @track totalApprovals = 0;

minWidth;
maxWidth;
col;
table;
x;
width;
@api approval; // Timesheet Approval record
@track selectedValue = 'All';
@track options = [];

loadListViews() {
    getListViews({ objectApiName: 'Timesheet_Approval__c' })
        .then(result =&gt; {
            if (result &amp;&amp; result.length &gt; 0) {
                this.options = [
                    ...result.map(listView =&gt; ({
                        label: listView.Name,
                        value: listView.DeveloperName
                    }))
                ];
            }
        })
        .catch(error =&gt; {
            console.error('Error retrieving list views:', error);
        });
}

handleChange(event) {
    this.selectedValue = event.detail.value;


}


connectedCallback() {
    setTimeout(() =&gt; {
        this.fetchData();
    });

    this.loadListViews();

    getTimeSheetApproval({ objType:'Timesheet_Approval__c', listView: this.selectedValue  })
.then(result =&gt; {
    let index = 0;
    this.approvals = result;
    this.approvals = this.approvals.map(approval =&gt; {
        index += 1;
        return {
            ...approval,
            url: '/lightning/r/Timesheet_Approval__c/'+approval.Id+'/view',
            sno: index,
            eurl: '/lightning/r/Employee__c/'+approval.Employee__r.Id+'/view',
            turl: '/lightning/r/Employee__c/'+approval.Timesheet__r.Id+'/view',
            aurl: '/lightning/r/Employee__c/'+approval.Approver__r.Id+'/view',
            ceurl: '/lightning/r/Employee__c/'+approval.Customer_Engagement__r.Id+'/view'
        };
    });
    this.totalApprovals = this.approvals.length;
    minutes()
        .then(result =&gt; {
            this.minutesSinceLastUpdate = result;
        })
        .catch(error =&gt; {
            console.error(error);
        });
})
.catch(error =&gt; {
    console.error(error);
});


}



renderedCallback() {
    if (this.isResizing &amp;&amp; this.col) {
        document.body.style.cursor = 'col-resize';
        this.width = Math.max(this.minWidth, Math.min(this.maxWidth, this.col.offsetWidth + this.x - this.table.offsetLeft));
        this.col.style.width = this.width + 'px';
    } else {
        document.body.style.cursor = '';
    }
}



fetchData() {
    this.table = this.template.querySelector('.slds-table');
    if (this.table) {
        const resizers = this.table.querySelectorAll('.slds-resizable__handle');
        resizers.forEach((resizer) =&gt; {
            resizer.addEventListener('mousedown', this.initResize.bind(this));
        });
    } else {
        setTimeout(() =&gt; {
            this.fetchData();
        }, 50);
    }
}

initResize(e) {
    this.col = e.target.closest('th');
    this.x = e.clientX;
    this.width = this.col.offsetWidth;
    this.minWidth = parseInt(window.getComputedStyle(this.col).minWidth) || 0;
    this.maxWidth = parseInt(window.getComputedStyle(this.table).width) || 0;
    this.isResizing = true;
    document.addEventListener('mousemove', this.doResize.bind(this));
    document.addEventListener('mouseup', this.stopResize.bind(this));
}

doResize(e) {
    if (this.isResizing &amp;&amp; this.col) {
        const dx = e.clientX - this.x;
        if (Math.abs(dx) &gt;= 5) {
            this.width = Math.max(this.minWidth, Math.min(this.maxWidth, this.width + dx));
            this.col.style.width = this.width + 'px';
            this.x = e.clientX;
        }
    }
}


stopResize() {
    this.isResizing = false;
    document.removeEventListener('mousemove', this.doResize);
    document.removeEventListener('mouseup', this.stopResize);
}

}

This is html code

<template>
    <!-- <lightning-card style="margin-top: 0%;"> -->
    <div class="slds-page-header slds-page-header_object-home">
        <div class="slds-page-header__row">
            <div class="slds-page-header__col-title">
                <div class="slds-media slds-no-space slds-grow">
                    <div class="slds-media__figure">
                        <span class="slds-icon_container slds-icon-standard-account">
                            <lightning-icon icon-name="standard:account" size="medium"></lightning-icon>
                        </span>
                    </div>
                    <div class="slds-media__body">
                        <p style="padding-bottom: 5px;" class=" slds-line-height_reset">
                            Timesheet Approvals
                        </p>
                    &lt;div class=&quot;triggerLinkTextAndIconWrapper slds-page-header__name&quot;&gt;
                        &lt;div class=&quot;slds-page-header__name-title&quot;&gt;
                            &lt;h1&gt;
                                &lt;span class=&quot;triggerLinkText selectedListView slds-page-header__title&quot;&gt;
                                    &lt;lightning-combobox 
                                        class=&quot;custom-combobox-container&quot;
                                        variant=&quot;label-hidden&quot; 
                                        value={selectedValue}
                                        options={options} 
                                        onchange={handleChange}&gt;
                                    &lt;/lightning-combobox&gt;
                                &lt;/span&gt;
                            &lt;/h1&gt;
                        &lt;/div&gt;
                    &lt;/div&gt;

                    &lt;div class=&quot;slds-p-top_small&quot;&gt;
                        &lt;p&gt;{totalApprovals} items • Updated {minutesSinceLastUpdate} &lt;/p&gt;
                    &lt;/div&gt;

                &lt;/div&gt;
            &lt;/div&gt;
        &lt;/div&gt;
    &lt;/div&gt;

&lt;/div&gt;



&lt;div class=&quot;slds-scrollable_x&quot;&gt;
    &lt;table class=&quot;slds-table slds-table_bordered slds-table_cell-buffer&quot;&gt;
        &lt;thead&gt;
            &lt;tr&gt;
                &lt;th scope=&quot;col&quot; &gt;
                    &lt;div class=&quot;slds-truncate&quot;&gt;&lt;/div&gt;
                &lt;/th&gt;
                &lt;th scope=&quot;col&quot; class=&quot;slds-resizable&quot;&gt;
                    &lt;div class=&quot;slds-truncate&quot; title=&quot;Timesheet Approver Name&quot;&gt;Timesheet Approver Name&lt;/div&gt;
                    &lt;input type=&quot;range&quot; min=&quot;60&quot; max=&quot;3840&quot; class=&quot;slds-resizable__input slds-assistive-text keyboardMode--skipArrowNavigation keyboardMode--pauseOnFocus&quot; aria-label=&quot;Timesheet Approver Name Column Width&quot; /&gt;
                    &lt;span class=&quot;slds-resizable__handle&quot;&gt;&lt;span class=&quot;slds-resizable__divider&quot;&gt;&lt;/span&gt;&lt;/span&gt;
                &lt;/th&gt;
                &lt;th scope=&quot;col&quot; class=&quot;slds-resizable&quot;&gt;
                    &lt;div class=&quot;slds-truncate&quot; title=&quot;Approval Status&quot;&gt;Approval Status&lt;/div&gt;
                    &lt;input type=&quot;range&quot; min=&quot;60&quot; max=&quot;3840&quot; class=&quot;slds-resizable__input slds-assistive-text keyboardMode--skipArrowNavigation keyboardMode--pauseOnFocus&quot; aria-label=&quot;Approval Status Column Width&quot; /&gt;
                    &lt;span class=&quot;slds-resizable__handle&quot;&gt;&lt;span class=&quot;slds-resizable__divider&quot;&gt;&lt;/span&gt;&lt;/span&gt;
                &lt;/th&gt;
                &lt;th scope=&quot;col&quot; class=&quot;slds-resizable&quot;&gt;
                    &lt;div class=&quot;slds-truncate&quot; title=&quot;Employee&quot;&gt;Employee&lt;/div&gt;
                    &lt;input type=&quot;range&quot; min=&quot;60&quot; max=&quot;3840&quot; class=&quot;slds-resizable__input slds-assistive-text keyboardMode--skipArrowNavigation keyboardMode--pauseOnFocus&quot; aria-label=&quot;Employee  Column Width&quot; /&gt;
                    &lt;span class=&quot;slds-resizable__handle&quot;&gt;&lt;span class=&quot;slds-resizable__divider&quot;&gt;&lt;/span&gt;&lt;/span&gt;
                &lt;/th&gt;
                &lt;th scope=&quot;col&quot; class=&quot;slds-resizable&quot;&gt;
                    &lt;div class=&quot;slds-truncate&quot; title=&quot;Customer Engagement&quot;&gt;Customer Engagement&lt;/div&gt;
                    &lt;input type=&quot;range&quot; min=&quot;60&quot; max=&quot;3840&quot; class=&quot;slds-resizable__input slds-assistive-text keyboardMode--skipArrowNavigation keyboardMode--pauseOnFocus&quot; aria-label=&quot;Customer Engagement Column Width&quot; /&gt;
                    &lt;span class=&quot;slds-resizable__handle&quot;&gt;&lt;span class=&quot;slds-resizable__divider&quot;&gt;&lt;/span&gt;&lt;/span&gt;
                &lt;/th&gt;
                &lt;th scope=&quot;col&quot; class=&quot;slds-resizable&quot;&gt;
                    &lt;div class=&quot;slds-truncate&quot; title=&quot;Timesheet&quot;&gt;Timesheet&lt;/div&gt;
                    &lt;input type=&quot;range&quot; min=&quot;60&quot; max=&quot;3840&quot; class=&quot;slds-resizable__input slds-assistive-text keyboardMode--skipArrowNavigation keyboardMode--pauseOnFocus&quot; aria-label=&quot;Timesheet Column Width&quot; /&gt;
                    &lt;span class=&quot;slds-resizable__handle&quot;&gt;&lt;span class=&quot;slds-resizable__divider&quot;&gt;&lt;/span&gt;&lt;/span&gt;
                &lt;/th&gt;
                &lt;th scope=&quot;col&quot; class=&quot;slds-resizable&quot;&gt;
                    &lt;div class=&quot;slds-truncate&quot; title=&quot;Approver&quot;&gt;Approver&lt;/div&gt;
                    &lt;input type=&quot;range&quot; min=&quot;60&quot; max=&quot;3840&quot; class=&quot;slds-resizable__input slds-assistive-text keyboardMode--skipArrowNavigation keyboardMode--pauseOnFocus&quot; aria-label=&quot;Approver Column Width&quot; /&gt;
                    &lt;span class=&quot;slds-resizable__handle&quot;&gt;&lt;span class=&quot;slds-resizable__divider&quot;&gt;&lt;/span&gt;&lt;/span&gt;
                &lt;/th&gt;

                &lt;th scope=&quot;col&quot; class=&quot;slds-resizable&quot;&gt;
                    &lt;div class=&quot;slds-truncate&quot; title=&quot;Action&quot;&gt;Action&lt;/div&gt;
                    &lt;input type=&quot;range&quot; min=&quot;60&quot; max=&quot;3840&quot; class=&quot;slds-resizable__input slds-assistive-text keyboardMode--skipArrowNavigation keyboardMode--pauseOnFocus&quot; aria-label=&quot;Action Column Width&quot; /&gt;
                    &lt;span class=&quot;slds-resizable__handle&quot;&gt;&lt;span class=&quot;slds-resizable__divider&quot;&gt;&lt;/span&gt;&lt;/span&gt;
                &lt;/th&gt;
            &lt;/tr&gt;
        &lt;/thead&gt;
        &lt;tbody&gt;
            &lt;template for:each={approvals} for:item=&quot;approval&quot; for:index=&quot;index&quot;&gt;
                &lt;tr key={approval.Id}&gt;
                    &lt;td  class=&quot;slds-truncate&quot; style=&quot;width: 50px;&quot;&gt;
                        {approval.sno}
                    &lt;/td&gt;
                    &lt;td data-label=&quot;Timesheet Approver Name&quot; class=&quot;slds-truncate&quot; title={approval.Name}&gt; &lt;a href={approval.url} target=&quot;_blank&quot;&gt;{approval.Name}&lt;/a&gt;&lt;/td&gt;

                    &lt;td data-label=&quot;Approval Status&quot; class=&quot;slds-truncate&quot; title={approval.Approval_Status__c}&gt;{approval.Approval_Status__c}&lt;/td&gt;
                    &lt;td data-label=&quot;Employee&quot; class=&quot;slds-truncate&quot; title={approval.Employee__r.Name}&gt;&lt;a href={approval.eurl} target=&quot;_blank&quot;&gt;{approval.Employee__r.Name}&lt;/a&gt;&lt;/td&gt;
                    &lt;td data-label=&quot;Customer Engagement&quot; class=&quot;slds-truncate&quot; title={approval.Customer_Engagement__r.Name}&gt;&lt;a href={approval.ceurl} target=&quot;_blank&quot;&gt;{approval.Customer_Engagement__r.Name}&lt;/a&gt;&lt;/td&gt;
                    &lt;td data-label=&quot;Created Date&quot; class=&quot;slds-truncate&quot; title={approval.Timesheet__r.Name}&gt;&lt;a href={approval.turl} target=&quot;_blank&quot;&gt;{approval.Timesheet__r.Name}&lt;/a&gt;&lt;/td&gt;
                    &lt;td data-label=&quot;Approver&quot; class=&quot;slds-truncate&quot; title={approval.Approver__r.Name}&gt;&lt;a href={approval.aurl} target=&quot;_blank&quot;&gt;{approval.Approver__r.Name}&lt;/a&gt;&lt;/td&gt;

                    &lt;td data-label=&quot;Action&quot; class=&quot;slds-truncate&quot;&gt;
                        &lt;lightning-button label=&quot;Edit&quot; onclick={handleEditClick} variant=&quot;neutral&quot; data-recordid={approval.Id}&gt;&lt;/lightning-button&gt;
                    &lt;/td&gt;
                &lt;/tr&gt;
            &lt;/template&gt;
        &lt;/tbody&gt;
    &lt;/table&gt;
&lt;/div&gt;
&lt;!-- &lt;/lightning-card&gt; --&gt;

</template>

RubenDG
  • 8,502
  • 2
  • 13
  • 23

1 Answers1

0

Using VF page i solved my error. This is the link that i referred: https://sfdcpanther.wordpress.com/2018/02/05/how-to-call-salesforce-api-from-lightning-component/

VF Page

<apex:page >
 Start_Of_Session_Id{!$Api.Session_ID}End_Of_Session_Id
</apex:page>

Apex Code

public static String fetchUserSessionId(){
    String sessionId = '';
    // Refer to the Page
    PageReference reportPage = Page.GetSessionIdVF;
    // Get the content of the VF page
    String vfContent = reportPage.getContent().toString();
    System.debug('vfContent '+vfContent);
    // Find the position of Start_Of_Session_Id and End_Of_Session_Id
    Integer startP = vfContent.indexOf('Start_Of_Session_Id') + 'Start_Of_Session_Id'.length(),
    endP = vfContent.indexOf('End_Of_Session_Id');
    // Get the Session Id
    sessionId = vfContent.substring(startP, endP);
    System.debug('sessionId '+sessionId);
    // Return Session Id
    return sessionId;
    }

I made use of the sessionId here

@AuraEnabled
    public static String filterCriteria(String objType, String listView){
      String sessionId = fetchUserSessionId();
        system.debug('ObjType: '+objType+'-- listView: '+listView);
    Id listViewId = [SELECT id FROM ListView WHERE developerName = :listView AND sObjectType=:objType].id;
    String ep = System.URL.getSalesforceBaseUrl().toExternalForm() + '/services/data/v43.0/sobjects/'+objType+'/listviews/'+listViewId+'/describe';
    HttpRequest req = new HttpRequest();
    req.setMethod('GET');
    req.setHeader('Authorization','Bearer '+sessionId);
    req.setEndpoint(ep);
    HttpResponse res = new Http().send(req);
    system.debug('Res body: '+res.getBody());
    queryWrapper qw = (queryWrapper)json.deserialize(res.getBody(), queryWrapper.class);

return (qw.query.containsIgnoreCase('WHERE')?qw.query.substringAfter('WHERE'):'');
}


public class queryWrapper{
    String query{get;set;}

}

  • Links tend to go bad over time, so it would be better if you were to reproduce the important parts of it here on this site (so that this answer can still be of use to others) – Derek F Apr 10 '23 at 11:10