1

I am trying to build a simple Lightning Web component to allow capturing both parent and child record details on single form. To explain i am taking an example of capturings single Account and Contact details on a single form.

As we cannot have attributes with default initialization like in AURA i have created a wrapper class holding the reference variable to Account and COntact objects as below.

public class Account_Contact_Wrapper {

    @AuraEnabled
    public Contact con{ 
        public get;
        public set;

   }
    @AuraEnabled
    public Account acc{ 

        public get;
        public set;

   }

    //default constructor to initiate class level variables

    public Account_Contact_Wrapper() {
        this.con = new Contact(FirstName='',LastName='');
        this.acc = new Account();

    }
}

I have created a apex controller which will initiate this wrapper class and return to a wire function call.

public class Account_Contact_Capturing_Controller {


//method to initiate wrapper class to pass on to LWC component 

@AuraEnabled(cacheable=true)
public  static Account_Contact_Wrapper initiateAccountContact() {

    return new Account_Contact_Wrapper();

}

}

I am calling this controller method from Lightning Web component controller using wire as a function.

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

export default class test_Component_not_to_deploy extends LightningElement {
    @track accountContact;

    @wire(initiateAccountContact)
    initiateAccountContact({data, error}){

        if(data){
            this.accountContact = data;
            this.error = undefined;
        }
        else if (error) {

            this.error = error;
            this.accountContact = undefined;
        }
    }


}

On console.log as well i see the data is successfully set from the wire function, but when i try to refer the variables in html the component is not rendering at all.

<template>
    <lightning-card title="test_Component_not_to_deploy" icon-name="custom:custom14">
        <div class="slds-m-around_medium">
            <lightning-input label="Name" value={accountContact.con.Name} ></lightning-input>
        </div>
    </lightning-card>
</template> 

But if i remove the variable binding in the value tag on lightning-input tag the component is loading successfully.

Below one is working:

        <lightning-input label="Name" value=""></lightning-input>

But if i try binding variable like below the component is not loading

        <lightning-input label="Name" value={accountContact.con.Name} ></lightning-input>

Is there anything missing in above logic, or is there any other way i can achieve initializing my wrapper class? As my form will be used to capture data from multiple objects i cannot go with lightning edit forms.

2 Answers 2

0

That is because you are not initializing the objects with 'properties'. Do as below:

public Account_Contact_Wrapper() {
    this.con = new Contact(FirstName='',LastName='');
    this.acc = new Account(Name='');
}

Added

Con does not have Name and so throwing error. Check in wrapper.

As we cannot have attributes with default initialization like in AURA

Not correct.

you can initialize in lwc as

@track account = { Name:'' };

3
  • Thanks, i actually have initialized the properties as well, still the same issue.
    – Rajasekhar
    Jul 26, 2019 at 10:18
  • you need to update the code in question to understand better Jul 26, 2019 at 11:39
  • thanks @salesforcesas , i have updated my question and i see the issue is not with adding the tag <template if:true={reporterDetails}>, I am still checking why is thig tag required and once i find the need of this tag will post a complete answer.
    – Rajasekhar
    Jul 26, 2019 at 16:06
0

Well I know Salesforce says the @track is a decorator to track changes deeper on the object

To tell the framework to observe changes to the properties of an object, decorate the field with @track.

https://developer.salesforce.com/docs/component-library/documentation/en/lwc/reference_decorators

also here they affirm it:

When manipulating complex types like objects and arrays, you must create a new object and assign it to the field for the change to be detected. To avoid such issues when working with complex objects, use the @track decorator to deeply tracks mutations made to the field value.

But also in the same documentation:

However, the framework doesn't observe mutations made to complex objects, such as objects inheriting from Object, class instances, Date, Set, or Map.

https://developer.salesforce.com/docs/component-library/documentation/en/lwc/lwc.reactivity_fields

In other words, the mutation of the object is not being observed.

you have two ways to solve your problem:

First way:

<template>
    <lightning-card title="test_Component_not_to_deploy" icon-name="custom:custom14">
        <template if:true={accountContact}
            <div class="slds-m-around_medium">
                <lightning-input label="Name" value={accountContact.con.Name} >. 
                </lightning-input>
            </div>
        </template>
    </lightning-card>
</template> 
import { LightningElement, track ,wire} from 'lwc';
import initiateAccountContact from '@salesforce/apex/Account_Contact_Capturing_Controller.initiateAccountContact';

export default class test_Component_not_to_deploy extends LightningElement {
    
    @wire(initiateAccountContact)
    wiredInitiateAccountContact; //name changed, you still can use in the function way
    
    get accountContact() {
        return this.wiredInitiateAccountContact?.data
    }
}

The second way is to get each field individually:

<template>
    <lightning-card title="test_Component_not_to_deploy" icon-name="custom:custom14">
        <div class="slds-m-around_medium">
            <lightning-input label="Name" value={contactName} >. 
            </lightning-input>
        </div>
    </lightning-card>
</template> 
import { LightningElement, track ,wire} from 'lwc';
import initiateAccountContact from '@salesforce/apex/Account_Contact_Capturing_Controller.initiateAccountContact';

export default class test_Component_not_to_deploy extends LightningElement {

    @wire(initiateAccountContact)
    wiredInitiateAccountContact; //name changed, you still can use in the function way
    
    get contactName() {
        return this.wiredInitiateAccountContact?.data?.con?.Name;
    }
}
1
  • just saw this question is really old ;o Nov 24, 2022 at 16:33

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .