2

I have an apex method that has an attribute and calls a web service:

   @AuraEnabled()
public static string getDetailEta(Integer idE) {
    system.debug('>> getDetailEta '+idE) ;
    myWebService.myWebServicePort newConn= new myWebService.myWebServicePort();
    myWebService.commonParams params = new myWebService.commonParams();
    myWebService.entp ent = new myWebService.entp();
    string result = '';
    string resultLog;
    params.login ='xxxx';
    try{
        ent = newConn.getDetailPCs(params,idE);
        system.debug(ent);
        result=JSON.serialize(ent);
        system.debug(JSON.serialize(ent.x_details));
        resultLog='succes';

    }catch(Exception e){
        system.debug(e);
        result='{"error": "'+e+'"}';
        resultLog='error';
    }
    MyLog.insertLog('getDetailEta',resultLog);
    system.debug(result);
    return result;

}

I use this as an imperative methode in my LWC inside the function eventHandler. The connectedCallBack function help me to get a value fired from an other component (see PubSub and PubSubContactDetails)

 import { LightningElement, track, wire } from 'lwc';
export default class PubsubContactDetails extends LightningElement {
   @track details;
   @track recordId='';
   @track error;
   @track result;
   @wire(CurrentPageReference) pageRef;
    connectedCallback() {
    registerListener('contactSelected', this.eventHandler, this);
}

disconnectedCallback() {
    unregisterAllListeners(this);
}
 eventHandler(value) {
    this.recordId = value;
    getdetails({idAccounts: this.recordId})
        .then(result => {
        this.details = JSON.parse(result);
        this.error = undefined;

        })
        .catch(error => {
        this.error = error;
        this.details = undefined;
        });}

I use {details} in my html page to display the data.

The function is working but i have to click twice on the button to display the data. Is there a solution to click only once, I dont want to use @wire method because my apex method is called when the components is created and it's not good for me.

I've run some tests that shows me that the apex method is returning the data on the first click, but still is not displayed until I click again.

  • Did you @track your details variable? Can we see more code? Also, there's nothing wrong with using @wired in most cases, you simply need to use reactive variables. I think you might be on the wrong path, as in an X-Y Problem. Please edit your question to include as much information as possible. Even better, we'd prefer a sscce that we can copy-paste to experiment with. – sfdcfox Apr 2 at 17:27
  • @wire runs (IIRC) before connectedCallback only if there is a state change for the bound var. Therefore, so long as you don't initiate a change in the wired value it won't fire. You need to create a defensive setter for setting this.recordId when it's truthy and set it to a private _recordId and use $_recordId in your wire. – tsalb Apr 3 at 8:17
  • @tsalb as you said wire runs before connectedCallback wich will call my webservice, I prefer not, and I'm not sure if this will solve my problem neither. . – Nassim Benkirane Apr 3 at 12:07
  • @sfdcfox I used track in my variables. I updated my question, I hope it's more clear – Nassim Benkirane Apr 3 at 12:08
  • It only runs if it sees a change in the reactive variable. I will give you an example later when I get a chance to. – tsalb Apr 3 at 14:12
1

Assuming your event fire mechanism (it's not clear in your code where exactly that is) is behaving correctly, the pubsub mechanism will pass the event to any subscribing component listening to contactSelected regardless of what's in the payload.

You might be hitting untruthy values on the first click.

Parent receiving event

 eventHandler(accountId) {
   console.log(accountId); // check this on first click
   if (accountId) {
     getdetails({idAccounts: accountId})
       .then(result => {
         // logic
       })
   }
 }

Child emitting event

  handleAccountIdSelected(event) {
    fireEvent(this.pageRef, 'contactSelected', event.target.value); // an accountId, we presume
  }

FYI: You do not need to @track variables you do not want to display in your template. You only need it if you have {recordId} in your template view.

Also, I know you explicitly want to omit wires, but this is how you would do it with one - because I think it's important to know both patterns:

  // private
  _accountId;

  @wire(getdetails, { idAccounts: '$_accountId' })
  wiredDetails(result) {
    if (result.data) {
      this.details = result.data; // pass it to the @tracked details
    } else if (result.error) {
      // handle error
    }
  }

  ...

  eventHandler(accountId) {
    if (accountId) {
      this._accountId = accountId;
    }
  }
  • Thank you @tsalb, the wire method worked perfectly. – Nassim Benkirane Apr 3 at 19:22
  • I figured out with my imperative method, the issue was that I was showing an other variable that equals this.details. Once I removed it and displayed this.details directly in my view it worked fine, maybe some issue with passing the value. – Nassim Benkirane Apr 3 at 19:32

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.