2

I'm a seasoned SFDC Dev, but fairly new to JS. I've read several documentations (Trailhead, Mozilla, ES6, W3) on JS since yesterday, trying to figure this out.

Why is this line...
this.mandatedActivities.push(activity);

...failing with... "Cannot read property 'mandatedActivities' of undefined"

import {LightningElement, wire} from 'lwc';
import getAllEventActivities from '@salesforce/apex/EventActivities_Ctrl.getAllEventActivities';

export default class EventActivityChecklist extends LightningElement {
  
  activities = [];
  mandatedActivities = [];

  @wire(getAllEventActivities) getAllEventActivitiesHandler({ data, error }) {
    if (data) {
      this.activities = data;

      if(this.activities) {
        this.activities.forEach(function(activity) {
          if(activity.Type__c == "Mandated Activity") {
            //Failing here: Cannot read property 'mandatedActivities' of undefined
            this.mandatedActivities.push(activity); 
          }
        })
      }
    } else if (error) {
      console.log(error);
    }
  }
}

New Code, based on SFDC Fox's answer

<template>
  <lightning-card title="Activities" icon-name="custom:custom14">
    <ul>
      <template for:each={mandatedActivities} for:item="activity">
          <span key={activity.id}>
            <div class="slds-col">
                <lightning-input type="checkbox" label={activity.Title__c} ></lightning-input>
            </div>
          </span>
      </template>
    </ul>
  </lightning-card>
</template>

import {LightningElement, wire} from 'lwc';
import getAllEventActivities from '@salesforce/apex/EventActivities_Ctrl.getAllEventActivities';

export default class EventActivityChecklist extends LightningElement {
  
  activities = [];
  mandatedActivities = [];

  @wire(getAllEventActivities) getAllEventActivitiesHandler({ data, error }) {
    if (data) {
      this.activities = data;

      if(this.activities) {
        this.activities.forEach((activity) => {
          if(activity.Type__c == "Mandated Activity") {
            this.mandatedActivities.push(activity); 
          }
        })
        console.log("mandatedActivities: ",this.mandatedActivities);
      }
    } else if (error) {
      console.log(error);
    }
  }
}

Console log shows here I now have an array of mandatedActivities. In the HTML, instead of looping through activities, I changed it to mandatedActivities. The prior displayed activities just fine. The latter does not display mandatedActivities in the view.

enter image description here

1 Answer 1

8
this.activities.forEach(function(activity) {

Using a regular function like this changes the this context to the activities variable, which isn't what you meant. Use an arrow function instead.

this.activities.forEach((activity) => {

The arrow function automatically retains the this it was defined in (the component), preventing problems like this from happening.

3
  • Thanks! Please see added new section "New Code, based on SFDC Fox's answer". I don't understand the difference between activities and mandatedActivities. Both are arrays of objects, correct? Jul 22, 2021 at 22:36
  • @RyanMcNeely If you don't use @track, changes to objects won't appear/render. Either track the variable, or use Array.map instead of Array.forEach+Array.push. I'm mobile, but feel free to search around on here for that issue.
    – sfdcfox
    Jul 22, 2021 at 22:49
  • Thanks @sfdcfox! Jul 22, 2021 at 23:15

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.