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

9
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

You must log in to answer this question.

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