Angular Ionic3 TypeScript - «TypeError: не удается прочитать свойство 'name' of undefined" после объединения из массива - PullRequest
0 голосов
/ 07 декабря 2018

Я очень новичок во всем этом, поэтому, пожалуйста, будьте осторожны со мной, я искал все, что я могу найти, но я просто не могу понять это.

ЯВ настоящее время я создаю приложение ionic3 и настроил списки покупок, чтобы пользователи могли добавлять рецепт в список покупок - который работает нормально - но я хочу настроить его так, чтобы при добавлении нескольких одинаковых предметов вместо двух экземпляровтого же элемента, он обновляет первый элемент, чтобы показать, что у него есть новые данные.Я могу отправлять элементы через службу и получать их на другой странице, а также сортировать их по алфавиту, но не могу заставить работать функцию объединения.

Заранее большое спасибо за вашу помощь.

Вот (надеюсь) соответствующий код:

import { Injectable } from "@angular/core";
import { Storage } from "@ionic/storage";
import { SLIngredient } from "../data/shopping-interface";

@Injectable()
export class ShoppingService {
  storedDay: SLIngredient[] = []
  storedWeek: SLIngredient[]
  userSL: SLIngredient[] = []
  sortedList: SLIngredient[] = []
  mergedItem: SLIngredient;
  mergedList: SLIngredient[] = [];

  constructor(private storage: Storage) {}

  getShoppingDay(day: number) {
    return this.storage.get('shoppingDay/' + day)
      .then(
        (storedDay: SLIngredient[]) => {
          this.storedDay = storedDay != null ? storedDay : [];
          return this.storedDay.slice();
        }
      )
  }

  getShoppingWeek(id: number) {
    return this.storage.get('shoppingWeek/' + id)
      .then(
        (storedWeek: SLIngredient[]) => {
          this.storedWeek = storedWeek != null ? storedWeek : [];
          return this.storedWeek.slice();
        }
      )
  }

  addItem(name: string, amount: number, measurement: string, completed: boolean) {
    this.userSL.push(new SLIngredient(name, amount, measurement, completed));
  }

  addItems(items: SLIngredient[]) {
    this.userSL.push(...items);
    this.sort()
    this.setUserSL();
    console.log(this.userSL)
  }

  getItems() {
    this.getUserSL;
    return this.userSL.slice();
  }

  sort() {
    this.sortedList = this.userSL.sort((itemA: SLIngredient, itemB: SLIngredient) => {
      const a = itemA.name.toLowerCase()
      const b = itemB.name.toLowerCase()

      if (a > b) return 1;
      if (a < b) return -1;
      if (a == b) {
        this.merge(itemA, itemB);
      }

      return 0
    })

    this.userSL = this.sortedList
  }

  merge(itemA: SLIngredient, itemB: SLIngredient) {
    const newAmount = +itemA.amount + +itemB.amount
    const itemC = new SLIngredient(itemA.name, newAmount, itemA.measurement, itemA.completed)
    this.sortedList.splice(this.sortedList.indexOf(itemA), 1, itemC);
    this.sortedList.splice(this.sortedList.indexOf(itemB), 1);
    // this.sortedList = Object.assign(itemA, itemB, itemC)
    // this.mergedList.push(new SLIngredient(merge.name, merge.amount, merge.measurement, merge.completed))
    // this.sortedList.push(this.mergedItem)
  }

  setUserSL() {
    this.storage.set('userSL', this.userSL)
  }

  getUserSL() {
    return this.storage.get('userSL')
      .then(
        (userSL: SLIngredient[]) => {
          this.userSL = userSL != null ? userSL : [];
          return
          this.userSL.slice();
        }
      )
  }
}

. Функция .sort () - это место, где выполняется функция, и именно с помощью функции .merge () я обнаружил проблему с.

Вот интерфейс:

export class SLIngredient {

constructor(
    public name: string,
    public amount: number,
    public measurement: string,
    public completed: boolean
){}

Я действительно ценю любую помощь, которую кто-либо может оказать в этом, поскольку я очень новичок во всем этом.

Еще раз спасибо.

РЕДАКТИРОВАТЬ

Когда я пытался позвонить

    sort(){
    this.userSL.reduce((reduced, element) => {
        const index = reduced.findIndex(r => r.name.toLowerCase() === element.name.toLowerCase());

        if (index === -1) return [...reduced, element];

        reduced[index].amount += element.amount;

        return reduced;
      }, []).sort((a, b) => {
        const nameA = a.name.toLowerCase()
        const nameB = b.name.toLowerCase()

        if (nameA > nameB) return 1;
        if (nameA < nameB) return -1;

        return 0
      })
}

, это вывод, который я получаю в журнале после добавления двух одинаковых рецептов в список покупок:

    (9) [{…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}]
    0: {name: "rolled oats", amount: "1", measurement: "cup"}
    1: {name: "milled flax seed", amount: "1-2", measurement: "tbsp"}
    2: {name: "ground cinnamon", amount: "1", measurement: "tsp"}
    3: {name: "non-diary milk of your choice - Coconut is best", amount: "1.5", measurement: "cups"}
    4: {name: "desiccated coconut", amount: "1", measurement: "tbsp"}
    5: {name: "banana", amount: "1", prep: "sliced"}
    6: {name: "frozen mixed berries or fresh seasonal berries (optional)", amount: "1", measurement: "handful"}
    7: {name: "raisins (optional)", amount: "1", measurement: "handful"}
    8: {name: "cocoa powder (optional)", amount: "1", measurement: "tsp"}
    length: 9
    __proto__: Array(0)

    (18) [{…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}]
    0: {name: "rolled oats", amount: "11", measurement: "cup"}
    1: {name: "milled flax seed", amount: "1-21-2", measurement: "tbsp"}
    2: {name: "ground cinnamon", amount: "11", measurement: "tsp"}
    3: {name: "non-diary milk of your choice - Coconut is best", amount: "1.51.5", measurement: "cups"}
    4: {name: "desiccated coconut", amount: "11", measurement: "tbsp"}
    5: {name: "banana", amount: "11", prep: "sliced"}
    6: {name: "frozen mixed berries or fresh seasonal berries (optional)", amount: "11", measurement: "handful"}
    7: {name: "raisins (optional)", amount: "11", measurement: "handful"}
    8: {name: "cocoa powder (optional)", amount: "11", measurement: "tsp"}
    9: {name: "rolled oats", amount: "11", measurement: "cup"}
    10: {name: "milled flax seed", amount: "1-21-2", measurement: "tbsp"}
    11: {name: "ground cinnamon", amount: "11", measurement: "tsp"}
    12: {name: "non-diary milk of your choice - Coconut is best", amount: "1.51.5", measurement: "cups"}
    13: {name: "desiccated coconut", amount: "11", measurement: "tbsp"}
    14: {name: "banana", amount: "11", prep: "sliced"}
    15: {name: "frozen mixed berries or fresh seasonal berries (optional)", amount: "11", measurement: "handful"}
    16: {name: "raisins (optional)", amount: "11", measurement: "handful"}
    17: {name: "cocoa powder (optional)", amount: "11", measurement: "tsp"}
    length: 18
    __proto__: Array(0)

ВТОРОЕ РЕДАКТИРОВАНИЕ

Это часть, с которой у меня все еще возникают проблемы:

    addItems(items: SLIngredient[]){
    this.userSL.push(...items);
    this.sort()
    this.setUserSL();
    console.log(this.userSL)
}

sort(){
    this.mergedList = this.userSL.reduce((reduced, element) => {
        const index = reduced.findIndex(r => r.name.toLowerCase() === element.name.toLowerCase());

        if (index === -1) return [...reduced, element];

        reduced[index].amount += element.amount;

        return reduced;
      }, []).sort((a, b) => {
        const nameA = a.name.toLowerCase()
        const nameB = b.name.toLowerCase()

        if (nameA > nameB) return 1;
        if (nameA < nameB) return -1;

        return 0
      })
      this.userSL = this.mergedList
}

setUserSL(){
    this.storage.set('userSL', this.userSL)
}

Поэтому я вызываю функцию addItems (), и она добавляет еек массиву, но он также сливает его сразу, а затем почему-то видит, что этот ингредиент имеет 2 из этогоself и поэтому, когда он добавляется снова, он удваивается вместо простого добавления.

Другая проблема заключается в том, что он отображает обновленное значение, а не просто помещает его в массив, который может быть отображен в другом месте.

     (9) [{…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}]
     0: {name: "banana/s", amount: 1, prep: "mashed"}
     1: {name: "rolled oats", amount: 1, measurement: "cup"}
     2: {name: "milled flaxseed", amount: 2, measurement: "tbsp"}
     3: {name: "ground cinnamon", amount: 1, measurement: "tsp"}
     4: {name: "non-dairy milk of your choice (I use Almond)", amount: 1.5, measurement: "cup/s"}
     5: {name: "frozen mixed berries or fresh seasonal berries (optional)", amount: 1, measurement: "handful/s"}
     6: {name: "raisins (optional)", amount: 1, measurement: "handful/s"}
     7: {name: "cocoa powder (optional)", amount: 1, measurement: "tsp"}
     8: {name: "desiccated coconut (optional)", amount: 2, measurement: "tsp"}

становится:

(9) [{…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}]
 0: {name: "banana/s", amount: 2, prep: "mashed"}
 1: {name: "cocoa powder (optional)", amount: 2, measurement: "tsp"}
 2: {name: "desiccated coconut (optional)", amount: 4, measurement: "tsp"}
 3: {name: "frozen mixed berries or fresh seasonal berries (optional)", amount: 2, measurement: "handful/s"}
 4: {name: "ground cinnamon", amount: 2, measurement: "tsp"}
 5: {name: "milled flaxseed", amount: 4, measurement: "tbsp"}
 6: {name: "non-dairy milk of your choice (I use Almond)", amount: 3, measurement: "cup/s"}
 7: {name: "raisins (optional)", amount: 2, measurement: "handful/s"}
 8: {name: "rolled oats", amount: 2, measurement: "cup"}
 length: 9
 __proto__: Array(0)

становится

(9) [{…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}]
0: {name: "banana/s", amount: 4, prep: "mashed"}
1: {name: "cocoa powder (optional)", amount: 4, measurement: "tsp"}
2: {name: "desiccated coconut (optional)", amount: 8, measurement: "tsp"}
3: {name: "frozen mixed berries or fresh seasonal berries (optional)", amount: 4, measurement: "handful/s"}
4: {name: "ground cinnamon", amount: 4, measurement: "tsp"}
5: {name: "milled flaxseed", amount: 8, measurement: "tbsp"}
6: {name: "non-dairy milk of your choice (I use Almond)", amount: 6, measurement: "cup/s"}
7: {name: "raisins (optional)", amount: 4, measurement: "handful/s"}
8: {name: "rolled oats", amount: 4, measurement: "cup"}
length: 9
__proto__: Array(0)

, и оно будет только удваиваться каждый раз, когда я добавляю что-то новое.И фактическая страница с ингредиентами (которая должна сказать 1 из большинства вещей) выглядит следующим образом:

screenshot

Еще раз спасибо за ваш вклад.

Ответы [ 2 ]

0 голосов
/ 07 декабря 2018

Вы меняете структуру массива в функции сортировки, и это большое нет-нет.Функция сортировки возвращает новый массив, отсортированный в соответствии с функцией сортировки, она не изменяет исходный массив.Сначала вы должны использовать reduce для объединения дубликатов, а затем сортировать массив.

userSL.reduce((reduced, element) => {
  const index = reduced.findIndex(r => r.name.toLowerCase() === element.name.toLowerCase();

  if (index === -1) return [...reduced, element];

  reduced[index].amount += element.amount;

  return reduced;
}, []).sort((a, b) => {
  const nameA = a.name.toLowerCase()
  const nameB = b.name.toLowerCase()

  if (nameA > nameB) return 1;
  if (nameA < nameB) return -1;

  return 0
})

В reduce мы добавляем один за другим элемент в результирующий массив (сокращенный), но если мы выясним,этот текущий элемент уже добавлен, мы просто обновляем количество уже добавленного элемента.Сортировка тогда прямолинейна, так как массив уже объединен.

Это не самая эффективная реализация, и она может не скомпилироваться (я пишу это прямо здесь), но идея проста и должна работать.

0 голосов
/ 07 декабря 2018

Я думаю, вы могли бы просто отфильтровать this.sortedList

this.sortedList.filter(a => a.name !== itemA.name && a.name !== itemB.name)

А затем вы добавили свой элемент C в массив.

...