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? Commented 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. Commented Jul 22, 2021 at 22:49
  • Thanks @sfdcfox! Commented Jul 22, 2021 at 23:15

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.