I am creating a shopping cart component with LWC and am struggling to get this to return data relating to the cart. I have a custom object to store the cart header details and am looking to have the controller initialise a new cart if no open carts exist for that user.
lwc-component.js
import {
LightningElement,
wire,
track
} from 'lwc';
/** get the current user's ID */
import Id from '@salesforce/user/Id';
/** Import the necessary Objects, fields and controller */
import getCartHeader from '@salesforce/apex/BoardCartController.getCartHeader';
export default class BoardShoppingCart extends LightningElement {
@track userId = Id;
times = 0;
@wire(getCartHeader, {
userId: '$userId'
})
cartHeader;
/** stuff used for debugging and console logging */
logOutStuff(dataToLog, logmessage) {
console.log(logmessage + JSON.stringify(dataToLog));
}
renderedCallback() {
this.times++;
console.log('render callback called this... ' + this.times);
this.logOutStuff(this.userId, 'The user ID is: ');
this.logOutStuff(this.cartHeader, 'The cart header is: ');
}
/************** END DEBUGGING *****************************/
}
BoardCartController.apex
public with sharing class BoardCartController {
@AuraEnabled(cacheable=true)
public static List<Boardstore_Cart__c> getCartHeader(String userId){
// Debugging
System.debug('the userID is: ' + userId);
List<Boardstore_Cart__c> currentCarts = new List<Boardstore_Cart__c>(
[SELECT Id, Name, Date_Created__c, Cart_Status__c
FROM Boardstore_Cart__c
WHERE ownerId =: userId
AND Cart_Status__c = 'Open'
LIMIT 1]);
System.debug('The current carts result: ' + currentCarts);
if(currentCarts.isEmpty()) {
// create a new cart and return that
System.debug('in the createCart function');
Boardstore_Cart__c singleToCreate = new Boardstore_Cart__c();
singleToCreate.Date_Created__c = System.Datetime.now();
singleToCreate.Cart_Status__c = 'Open';
singleToCreate.ownerId = userId;
System.debug('the single to create is: ' + singleToCreate);
// Insert into database
try {
Database.SaveResult results = Database.insert(singleToCreate);
System.debug('logging out the results of the DB save: ' + results);
} catch(DmlException e) {
System.debug('in the catch block: ' + e.getMessage());
}
// TODO: add default shipping fields.
// reset current carts
currentCarts = [SELECT Id, Name, Date_Created__c, Cart_Status__c
FROM Boardstore_Cart__c
WHERE ownerId =: userId
AND Cart_Status__c = 'Open'
LIMIT 1];
}
return currentCarts;
}
}
Expected behaviour is that the component will mount, calling the Apex controller method getCartHeader and passing in a string that represents the userID. The controller will take that string, search for an open cart record and if found, return that. If not, it will create a new cart record and return that.
Actual behaviour the controller is firing an exception for too many DML statements (1) and not creating the cart. If I manually create the cart, the code completes but the js side doesn't log the cartHeader details..
How can I get this controller to create the new cart record as required? I have tried removing the (cacheable=true) after reading this in the docs:
To improve runtime performance, annotate the Apex method with @AuraEnabled(cacheable=true), which caches the method results on the client. To set cacheable=true, a method must only get data, it can’t mutate (change) data.
However, when this is removed - the apex controller doesn't fire at all...