unshiftObject method is not working in ember

55 Views Asked by At

I have the array of Objects and want to concat only the list property of all objects and create a new array. So I have a "combinedList" getter in the below code to combine the list if array length is greater than 1 else just return the 1st items list property. This returned array will be used in the template file to display. If any new item is added, the addComment function will be called with the newly added item and push that to the "combinedList" array.

The problem here is, if the objArr length is less than 1, the newItem is pushed to the "combineList". But, if it is greater than 1, newItem is not pushed to the "combinedList" array.

Can anyone please help me to figure out the cause for this issue?

export default class YourComponent extends Component {
  objArr = [ {id:1, list:[1,2,3]}, {id:2, list:[3,4]} ];

  get combinedList() {
    if (this.objArr.length > 1) {
      let list = [];
      this.objArr.forEach((item) => {
        list.push(...item.list);
      });
      return list;
    }
    return this.objArr[0].list;
  }

  // Call this method when adding a new item
  addComment(newItem) {
    this.combinedList.unshiftObject(newItem);
  }
}
1

There are 1 best solutions below

1
NullVoxPopuli On

Given this code:

export default class YourComponent extends Component {
  objArr = [ {id:1, list:[1,2,3]}, {id:2, list:[3,4]} ];

  get combinedList() {
    if (this.objArr.length > 1) {
      let list = [];
      this.objArr.forEach((item) => {
        list.push(...item.list);
      });
      return list;
    }
    return this.objArr[0].list;
  }

  // Call this method when adding a new item
  addComment(newItem) {
    this.combinedList.unshiftObject(newItem);
  }
}

A couple things will make your life easier:

  1. getters may not mutate data
    • no violation here, so we're good
  2. ℹ️ getters re-run every time they are called (they are like methods)
    • this means that each time combinedList is accessed, you could get a new list object.
  3. unshiftObject is not a property on Array.prototype -- you may want unshift: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/unshift
  4. methods must have a bound this (JavaScript goofiness)
  5. if the UI is going to render combinedList in anyway, it needs to auto-tracking enabled

Resolving #2

add a @cached on it so that it'll be a stable reference each time combinedList is accessed:

import { cached } from '@glimmer/tracking';

// ...

@cached
get combinedList() {
  // ...  
}

Resolving #3

  addComment(newItem) {
    this.combinedList.unshift(newItem);
  }

Resolving #4

addComment = (newItem) => this.combinedList.unshift(newItem);

Resolving #5

import { TrackedArray } from 'tracked-built-ins';


// ...

  @cached
  get combinedList() {
    if (this.objArr.length > 1) {
      let list = new TrackedArray();
      this.objArr.forEach((item) => {
        list.push(...item.list);
      });
      return list;
    }
    return new TrackedArray(this.objArr[0].list);
  }

this will allow unshift to update the UI