[SalesForce] NoErrorObjectAvailable Script error in Lightning when Computing Total of Values From Multiple JS Functions in Salesforce LWC

I have a custom LWC page which displays and computes sections based on conditional rendering of a multi-select picklist field. I do not have any problem with regards to the display/hide and computations of each sections but I am encountering following error when I try to click a field which should total all section values. Please take note that Sections A, B, and C are displaying all expected computations.

By the way, I test the LWC page by embedding it in aura component and overriding standard new button.

For the sake of shorter and accurate posting, I won't include the aura component here as well as the multi-select picklist part since I do not encounter problems on both.

Encountered Error

enter image description here

enter image description here

I tried to insert console.log so I can see the result but it doesn't reach the console.log statement. I thought adding values from multiple functions is simple, but looks like this isn't the case.

Meanwhile, here are the current codes I have:

HTML FILE

<template>

    <div if:true={displayModal} class="slds-modal__container">        

        <lightning-messages></lightning-messages>
    
        <template if:true={customObj1Record}>            

            <header class="slds-modal__header">
                <h2 id="modal-heading-01" class="slds-text-heading_medium slds-hyphenate">new record</h2>
            </header>

            <div class="slds-modal__content slds-var-p-around_medium slds-grid slds-wrap slds-scrollable_y">

            <div class="slds-section slds-col slds-size_2-of-2">
                <div class="slds-section__title slds-theme_shade primaryPaletteBorder test-id__section-header-container">Section A</div>        
            </div>

            <div class="slds-col slds-size_2-of-2">       
                <lightning-input 
                    type="number" 
                    name="Field1" 
                    label="Field1" 
                    value={customObj1Record.Field1__c}
                    onchange={handleField1Change}>
                </lightning-input>
            </div>  

            <div class="slds-col slds-size_2-of-2">       
                <lightning-input 
                    type="number" 
                    name="Field2" 
                    label="Field2" 
                    value={customObj1Record.Field2__c}
                    onchange={handleField2Change}>
                </lightning-input>
            </div>  

            <div class="slds-col slds-size_2-of-2">       
                <lightning-input 
                    type="number" 
                    name="Field3" 
                    label="Field3" 
                    value={customObj1Record.Field3__c}
                    onchange={handleField3Change}>
                </lightning-input>
            </div> 

            <div class="slds-section slds-col slds-size_2-of-2">
                <div class="slds-section__title slds-theme_shade primaryPaletteBorder test-id__section-header-container">Section B</div>        
            </div>

            <div class="slds-col slds-size_2-of-2">       
                <lightning-input 
                    type="number" 
                    name="Field4" 
                    label="Field4" 
                    value={customObj1Record.Field4__c}
                    onblur={handleField4Change}>
                </lightning-input>
            </div>  

            <div class="slds-col slds-size_2-of-2">       
                <lightning-input 
                    type="number" 
                    name="Field5" 
                    label="Field5" 
                    value={customObj1Record.Field5__c}
                    onchange={handleField5Change}>
                </lightning-input>
            </div>  

            <div class="slds-col slds-size_2-of-2">       
                <lightning-input 
                    type="number" 
                    name="Field6" 
                    label="Field6" 
                    value={customObj1Record.Field6__c}
                    onchange={handleField6Change}>
                </lightning-input>
            </div>

            <div class="slds-section slds-col slds-size_2-of-2">
                <div class="slds-section__title slds-theme_shade primaryPaletteBorder test-id__section-header-container">Section C</div>        
            </div>

            <div class="slds-col slds-size_2-of-2">       
                <lightning-input 
                    type="number" 
                    name="Field7" 
                    label="Field7" 
                    value={customObj1Record.Field7__c}
                    onblur={handleField7Change}>
                </lightning-input>
            </div>  

            <div class="slds-col slds-size_2-of-2">       
                <lightning-input 
                    type="number" 
                    name="Field8" 
                    label="Field8" 
                    value={customObj1Record.Field8__c}
                    onchange={handleField8Change}>
                </lightning-input>
            </div>  

            <div class="slds-col slds-size_2-of-2">       
                <lightning-input 
                    type="number" 
                    name="Field9" 
                    label="Field9" 
                    value={customObj1Record.Field9__c}
                    onchange={handleField9Change}>
                </lightning-input>
            </div>

            <div class="slds-section slds-col slds-size_2-of-2">
                <div class="slds-section__title slds-theme_shade primaryPaletteBorder test-id__section-header-container">Section D</div>        
            </div>

            <div class="slds-col slds-size_2-of-2">       
                <lightning-input 
                    type="date" 
                    name="Field10" 
                    label="Field10" 
                    value={customObj1Record.Field10__c}
                    onblur={handleField10Change}>
                </lightning-input>
            </div>  

            <div class="slds-col slds-size_2-of-2">       
                <lightning-input 
                    type="text" 
                    name="Field11" 
                    label="Field11" 
                    value={customObj1Record.Field11__c}
                    onblur={handleField11Change}>
                </lightning-input>
            </div>

            <div class="slds-section slds-col slds-size_2-of-2">
                <div class="slds-section__title slds-theme_shade primaryPaletteBorder test-id__section-header-container">Computations</div>        
            </div>

            <div class="slds-col slds-size_2-of-2">
                <label class = "slds-var-m-right_small">Section A Total</label>
                <div class="slds-var-m-right_small">{displaySectionAText}</div>
            </div>

            <div class="slds-col slds-size_1-of-2">
                <label class = "slds-var-m-right_small">Section B Total</label>
                <div class="slds-var-m-right_small">{displaySectionBText}</div>
            </div>

            <div class="slds-col slds-size_1-of-2">
                <label class = "slds-var-m-right_small">Section C Total</label>
                <div class="slds-var-m-right_small">{displaySectionCText}</div>
            </div>

            <div class="slds-col slds-size_2-of-2">
                <label class = "slds-var-m-right_small">Overall Total</label>
                <div class="slds-var-m-right_small">{displayTotalText}</div>
            </div>

            </div>           

        </template>

    </div>
    
</template>

JS FILE

import { LightningElement, track} from 'lwc';

import CUSTOMOBJECT1_OBJECT from '@salesforce/schema/CustomObject1__c';
    
    export default class CustomObject1LWC {

    @track displayModal = true; 
    @track customObj1Record = {CustomObject1__c:""};
    @track sectionAInt = 0;
    @track sectionAText;
    @track sectionBInt = 0;
    @track sectionBText;
    @track sectionCInt = 0;
    @track sectionCText;
    @track totalInt = 0;
    @track totalText;
    @track displaySectionAText = '0 Stars';
    @track displaySectionBText = '0 Stars';
    @track displaySectionCText = '0 Stars';
    @track displayTotalText = '0 Overall Stars';
    

    handleField1Change(event) {
        this.customObj1Record.Field1__c = event.target.value;
    }

    handleField2Change(event) {
        this.customObj1Record.Field2__c = event.target.value;
    }

    handleField3Change(event) {
        this.customObj1Record.Field3__c = event.target.value;
    }

    handleField4Change(event) {
        this.customObj1Record.Field4__c = event.target.value;
        this.computeSectionA();
    }

    handleField5Change(event) {
        this.customObj1Record.Field5__c = event.target.value;
    }

    handleField6Change(event) {
        this.customObj1Record.Field6__c = event.target.value;
    }

    handleField7Change(event) {
        this.customObj1Record.Field7__c = event.target.value;
        this.computeSectionB();
    }

    handleField8Change(event) {
        this.customObj1Record.Field8__c = event.target.value;
    }

    handleField9Change(event) {
        this.customObj1Record.Field9__c = event.target.value;
    }

    handleField10Change(event) {
        this.customObj1Record.Field10__c = event.target.value;
        this.computeSectionC();
    }

    handleField11Change(event) {
        this.customObj1Record.Field11__c = event.detail.value;
        this.computeTotalAll();
    }

    computeSectionA() {
        this.sectionAInt = (parseInt(this.customObj1Record.Field1__c) || 0) + (parseInt(this.customObj1Record.Field2__c) || 0) + (parseInt(this.customObj1Record.Field3__c) || 0);

        var sectionAText;                       
                                  
        sectionAText = this.sectionAInt;
        if(this.sectionAInt != null) {
            this.displaySectionAText = sectionAText + ' ' + 'Stars';  
        }    
        return this.sectionAInt;                        
    }

    computeSectionB() {
        this.sectionBInt = (parseInt(this.customObj1Record.Field4__c) || 0) + (parseInt(this.customObj1Record.Field5__c) || 0) + (parseInt(this.customObj1Record.Field6__c) || 0);                          

        var sectionBText; 

        sectionBText = this.sectionBInt;    
        if(this.sectionBInt != null) {
            this.displaySectionAText = sectionBText + ' ' + 'Stars';    
        }     
        return this.sectionBInt;                                       
    }

    computeSectionC() { 
        this.sectionCInt = (parseInt(this.customObj1Record.Field7__c) || 0) + (parseInt(this.customObj1Record.Field8__c) || 0) + (parseInt(this.customObj1Record.Field9__c) || 0);                     

        var sectionCText; 

        sectionCText = this.sectionCInt;  
        if(this.sectionCInt != null) {
            this.displaySectionAText = sectionCText + ' ' + 'Stars';     
        }      
        return this.sectionCInt;                                                
    }

    computeTotalAll() {
        var sectionASum = this.computeSectionA();
        var sectionBSum = this.computeSectionB();
        var sectionCSum = this.computeSectionC();
        this.totalInt = sectionASum + sectionBSum + sectionCSum; 
        var total; 
        total = this.totalInt;      
        if(this.totalInt != null) {
            this.displaySectionAText = total + ' ' + 'Overall Stars';       
        }                           
        else {
            this.displaySectionAText = '0' + ' ' + 'Overall Stars';   
        }   
        return this.totalInt;                       
    }

}

Best Answer

You can't call another method in the class without this:

// Won't work
var sectionASum = computeSectionA();
// Correct
var sectionASum = this.computeSectionA();

You're not checking for invalid numbers, so you can end up with NaN when adding parseInt:

    // Won't work
    this.sectionAInt =
        parseInt(this.customObj1Record.Field1__c) +
        parseInt(this.customObj1Record.Field2__c) +
        parseInt(this.customObj1Record.Field3__c);
    // Correct
    this.sectionAInt =
        (parseInt(this.customObj1Record.Field1__c) || 0) +
        (parseInt(this.customObj1Record.Field2__c) || 0) +
        (parseInt(this.customObj1Record.Field3__c) || 0);

You didn't return a value from your method, so you don't have values to add in computeTotalAll:

// Won't work
computeSectionA() {
    this.sectionAInt =
        (parseInt(this.customObj1Record.Field1__c) || 0) +
        (parseInt(this.customObj1Record.Field2__c) || 0) +
        (parseInt(this.customObj1Record.Field3__c) || 0);
    this.displaySectionAText = `${sectionAText} Stars`;
}
// Correct
computeSectionA() {
    this.sectionAInt =
        (parseInt(this.customObj1Record.Field1__c) || 0) +
        (parseInt(this.customObj1Record.Field2__c) || 0) +
        (parseInt(this.customObj1Record.Field3__c) || 0);
    this.displaySectionAText = `${sectionAText} Stars`;
    return this.sectionAInt;
}

Other mentions...

You don't need to use @track for non-array/non-object values. This happens automatically.

You can consolidate your change handlers to just:

handleFieldChange(event) {
    this.customObj1Record[event.target.dataset.fieldName] = event.target.value;
    this.computeTotalAll();
}

By changing your input fields:

<lightning-input 
    type="text" 
    name="Field1" 
    label="Field1" 
    data-field-name="Field1__c"
    value={customObj1Record.Field1__c}
    onchange={handleFieldChange}>

This changes 33 lines of code to just 3 in exchange for 11 lines of markup code. Not a bad exchange. You could probably just call computeTotalAll for every change, too, for consistency in the UI.