I'm new to LWC. And after going through the entire "Build Lightning Web Components" trail, I must still be missing something fundamental about how the uiRecordApi getRecordgetRecord
method works, or maybe I just don't understand Javascript half as well as I think.
When using @wire(getRecord, ...)@wire(getRecord, ...)
, I get back an object with data as expected, except. But I can't access that data in the way I'm used to. Dot notation, Object.keys()Object.keys()
, and even JSON.parse(JSON.stringify(Object))JSON.parse(JSON.stringify(Object))
are failing in ways that suggest that the object is undefined in some cases.
import { LightningElement, api, track, wire } from 'lwc';
import { getRecord, getFieldValue } from 'lightning/uiRecordApi';
// ...
import APP_NAME from '@salesforce/schema/Application__c.Name';
// etc...
export default class myApplicationThing extends LightningElement {
@api recordId; // Application__c.Id
@track app; // Application__c record
@track appName;
// ...
@wire(getRecord, { recordId: '$recordId', fields })
loadRecord ({ error, data }) {
if (data) {
this.app = data;
this.error = undefined;
this.appName = getFieldValue(data, APP_NAME); // I can use the value
// of appName just fine if I get it this way, e.g. with {appName}
// in the HTML template
// ...
} else if (error) {
// ...
}
}
// Called from a {testMe} in the HTML template
get testMe() {
console.log(this.app); // returns a Proxy
console.log(JSON.stringify(this.app)); // returns a JSON as expected:
/*
{
"apiName": "Application__c",
"childRelationships": {},
"fields": {
"Name": {
"displayValue": null,
"value": "A-0801096"
},
"Service_Area__c": {
"displayValue": null,
"value": "UT"
},
...
},
...
} */
console.log(this.app.fields.Name.value); // throws error:
/* afterRender threw an error in 'c:crmApplication'myApplicationThing'
[Cannot read property 'fields' of undefined] */
console.log(this.app.keys()); // throws error:
/* Cannot read property 'keys' of undefined */
console.log(JSON.parse(JSON.stringify(this.app))); // throws error:
/* Unexpected token u in JSON at position 0 */
return '?!';
}
I could theoretically use getFieldValuegetFieldValue
to get all the field values on my record, but I'm building up a large form with lots of fields, and trying to nest components within components according to best practice. So in reality this would mean calling out each separate field a whole bunch of times in different places in a way that is super verbose and hard to maintain. I'd much rather pass an object around vs. passing around dozens of primitives.
By the time I got the answer from @BritishBoyinDC (well done, sir!), I had been pondering the nature of ansync wired data, and I solved my problem by wrapping the entire component HTML like so:
Everything inside that if:true directive that relies on the wired record data holds it horses and waits for the data to show up. :-)
By the way, console.log(this.app)
and console.log(JSON.stringify(this.app))
work because you can both log and JSON-stringify an undefined object in JavaScript without incurring an error. On the other hand, if you try to access properties on an undefined object, an error comes up.