Syntax guide for working with Salesforce Web Components
UPDATE
My initial understanding of the wired property was incorrect.
While trying to reproduce the issue, I had used data.length
and thus had come to the conclusion that unless the wired property is referred in HTML, it does not get populated. Whereas in reality, once the component is rendered, the wired property does get populated.
Upon testing further found that the actual issue is that data
is returned as JSON, and that length
is not a valid property on the JSON being returned, which causes an error. So to verify if the property is blank or not, the approach that should be used here should be as:
if(this.studentCourseRelationships.data !== undefined) {
if(JSON.stringify(this.contacts.data).length > 0);
return true; // data populated
} else {
return false; // no data
}
OR
Just use undefined
if(this.studentCourseRelationships.data !== undefined) {
return true; // data populated
} else {
return false; // no data
}
UPDATE
Calling Apex Method Imperatively
While you can wire an Apex method, you can also call it imperatively. To do so, you will need to utilize it in your hasCourses()
function as below, and then verify it on HTML. This way you don't need to go through the approach mentioned earlier in the answer.
// declare a tracked variable
@track myStudentCourseRelationships;
get handleCourses() {
// invoke the Apex method here
getCourseData()
.then(result => {
this.myStudentCourseRelationships = result;
})
.catch(error => {
this.error = error;
});
// myStudentCourseRelationships will be returned as a JSON
// verify if you get a valid JSON, then return accordingly
}
Contents not valid have been striked-off and updated with relevant findings.
Utilizing wired Apex method
After trying to reproduce the scenario, it seems the wired service does get invoked only when it is referred in the HTML. So in your scenario studentCourseRelationships
gets populated as JSON only when it's referred in the HTML when it's referred as . So if you try to find the {studentCourseRelationships.data}
length
of this attribute before it getting populated, that's when you will receive the error.
The option that I could see working is to display the contents only when length
is not 0, is by using something as below. The idea is to ensure that studentCourseRelationships
gets populated before you call hasCourses
which checks on a valid data.length
.
<template if:true={studentCourseRelationships.data}>
<template if:true={hasCourses}>
...
</template>
</template>
I will continue to see if there's a better option.
You need to check if the objects are yet populated:
get hasCourses() {
return this.studentCourseRelationships &&
this.studentCourseRelationships.data &&
this.studentCourseRelationships.data.length > 0;
}
The && operator evaluates the right-hand value only if the left-side is "truthy", and the > operator only returns true if the result is a number and is greater than 0.