5

I am trying to use wire service to get the geo data from a record, and expecting the component will rerender every time wire service gets the data.

This is how my component JS looks like,

import LONGITUDE_FIELD from '@salesforce/schema/Boat__c.Geolocation__Longitude__s';
import LATITUDE_FIELD from '@salesforce/schema/Boat__c.Geolocation__Latitude__s';
import { getRecord } from 'lightning/uiRecordApi';
const BOAT_FIELDS = [LONGITUDE_FIELD, LATITUDE_FIELD];

export default class BoatMap extends LightningElement {
// private
@track boatId;

// Getter and Setter to allow for logic to run on recordId change
// this getter must be public
@api
get recordId() {
  return this.boatId;
}
set recordId(value) {
  this.setAttribute('boatId', value);
  this.boatId = value;
}

// Getting record's location to construct map markers using recordId
// Wire the getRecord method using ('$boatId')
@wire(getRecord, { recordId: '$boatId', fields: BOAT_FIELDS })
wiredRecord({error, data}) {
  // Error handling
  if (data) {
    this.error = undefined;
    const longitude = data.fields.Geolocation__Longitude__s.value;
    const latitude = data.fields.Geolocation__Latitude__s.value;
    // this updates the map marker array
    this.updateMap(longitude, latitude);
  } else if (error) {
    this.error = error;
    this.boatId = undefined;
    this.mapMarkers = [];
  }
}

// receives message from message lms channel
// from the debug statement I can tell that it is receiving the updated ids from the channel
// here I am expecting that on setting the id received from channel to this.boatId
// because this.boatId is a reactive property in wired service it will invoke a getRecord wire service call. But it doesn't do that.
handleMessage(message) {
  console.log('message received');
  console.log(message.recordId);
  this.boatId = message.recordId;
  //this.recordId = message.recordId;
  console.log(this.boatId);
}

My understanding and expectation is because I am using this.botId as reactive property ('$boatId') in my getRecord wire call, every time the value of this.boatId is updated wire service should fetch the data (either from service or from cache) and re-render the component with the new geo-data by invoking this.updateMap

I also tried manually refreshing the wired service fetch data using refreshApex, but even that approach didn't work.

3
  • Not a complete answer, but note that you set this.boatId = undefined in the case of an error. The wire won't fire again at that point but nothing will then be presented and nothing will happen until something else later sets the boatId to a definite value. I wonder if there is an issue with how you registered handleMessage - are you sure you are getting the function correctly invoked with the correct contextual "this" binding? If it isn't then setting this.boatId will not actually be updating your LWC instance and thus will not cause the wire to react.
    – Phil W
    Aug 7, 2020 at 15:36
  • 1
    thanks @PhilW for your reply. I found the actual cause though. It was because LWC doesn't like geo fields to be imported from the schema and used in wire service which is why it is failing. Once I replaced it with fields: ['Boat__c.Geolocation__Longitude__s', 'Boat__c.Geolocation__Latitude__s'] it worked like charm.
    – Yogesh D
    Aug 7, 2020 at 15:38
  • 1
    I suggest you add an answer to your own question for future seekers of answers that explains what you found. I'll happily up vote it.
    – Phil W
    Aug 7, 2020 at 15:40

1 Answer 1

11

Documenting the resolution I found to my question here,

so apparently LWC doesn't like if you you use imported references to the geo-location compound fields which is why this doesn't work with wired service:

import LONGITUDE_FIELD from ' @salesforce/schema/Boat__c.Geolocation__Longitude__s';
import LATITUDE_FIELD from '@salesforce/schema/Boat__c.Geolocation__Latitude__s';
const BOAT_FIELDS = [LONGITUDE_FIELD, LATITUDE_FIELD];

If you change that to this instead it works fine with the wire:

const LONGITUDE_FIELD = 'Boat__c.Geolocation__Longitude__s';
const LATITUDE_FIELD = 'Boat__c.Geolocation__Latitude__s';
const BOAT_FIELDS = [LONGITUDE_FIELD, LATITUDE_FIELD];

I was able to get to this with the help of this answer here, which in turn references the documentation that specifically says:

A compound geolocation field is supported through its constituent fields. To access a geolocation field, use its constituent fields with string syntax.

(emphasis added for clarity)

3
  • Why was this answer down voted without an explanatory comment?
    – Phil W
    Aug 7, 2020 at 16:36
  • @PhilW T'wasn't me. I thought this answer was perfectly fine.
    – sfdcfox
    Aug 7, 2020 at 19:03
  • If you try to import the fields something strange happens after deploying to an org (in my case a sandbox). I was trying to figure out was going on diff'ed against org and saw it was translating my imports into something else: what I pushed: import fieldname from '@salesforce/schema/object__c.Geolocation__Latitude__s'; what I retrieved: import fieldname from '@salesforce/schema/object__c.Geolocation__c' For whatever reason it's perfectly happy to see your fully scoped field import and replace it with what it likes. That's not so nice.
    – torpy
    Aug 31, 2020 at 14:42

You must log in to answer this question.

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