1

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...

3

You cannot do DML in Apex Aura Methods declared as (cacheable=true).

If in LWC , if Aura Method does not have (cacheable=true) you cannot use @wire to call apex.

From Docs:

To use @wire to call an Apex method, you must set cacheable=true.

You have to call apex imperatively.

export default class BoardShoppingCart extends LightningElement {
  @track userId = Id;
  times = 0;
  @api cardHeader;

    handleLoad() {
        getCartHeader({userId: this.userId})
            .then(result => {
                this.cardHeader = result;
            })
            .catch(error => {
                this.error = error;
            });
    }
}

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.