Angular8 / TypeScript: map.set () не является функцией - PullRequest
0 голосов
/ 15 апреля 2020

У меня есть классы meal и mealplan. Свойством план питания является карта foodsPerWeek , которая содержит день недели в качестве ключа и объект приема пищи .

food.ts

export class Meal {
  id: number;
  name: string;
  price: number;
}

foodplan.ts

export class Mealplan {
  id: number;
  mealsPerWeek: Map<Weekday, Meal>;

  constructor() {
    this.mealsPerWeek = new Map();
  }
}

weekday.ts

export enum Weekday {
   Monday = 0,
   Tuesday = 1,
   Wednesday = 2,
   Thursday = 3,
   Friday = 4
}

Теперь я хочу добавить еду в свойство карты foodsPerWeek с помощью PostMapping и реактивной формы (Angular). Данные из формы отправляются компоненту:

foodplan-detail.component.ts

export class MealplanDetailComponent implements OnInit {
 addMealToMealplanForm: FormGroup;
 private meals: Meals[];
 private mealplan: Mealplan;
 private meal: Meal;

 // constructor() { }
 ngOnInit() {
  this.getMeals();
  this.getMealplan();

 .... (form constructor)
 }

 addMealToMealplan(): void {
      this.mealplanService.addMealToMealplan(this.mealplan, this.selectedMeal.value, 
      this.selectedWeekday.value).subscribe(() => {
        this.mealplan.mealsPerWeek.set(this.selectedWeekday.value, 
this.selectedEssen.value);
      });
    }
  }

  get selectedMeal() {
    return this.addMealToMealplanForm.get('meal');
  }

  get selectedWeekday() {
    return this.addMealToMealplanForm.get('weekday');
  }

Основная проблема заключается в том, что this.mealplan.mealsPerWeek.set(this.selectedWeekday.value, this.selectedEssen.value); не за работой. Консоль напечатает: this.mealplan.mealsPerWeek.set is not a function.

Важно то, что значение this.selectedWeekday.value является идентификатором перечисления, а значение this.selectedEssen.value является объектом приема пищи.

Является ли метод "установить", возможно, неправильный метод? Нужно ли использовать другой метод?

Метод в плане питания Сервис:

  addMealToMealplan(mealplan: Mealplan | number, meal: Meal | number, weekday: number): Observable<Meal> {
    const mealplanId = typeof mealplan === 'number' ? mealplan : mealplan.id;
    const mealId = typeof meal === 'number' ? meal : meal.id;

    const url = `${this.mealplanUrl}/${mealplanId}/add/${mealId}/wt=${weekday}`;
    return this.http.post<Meal>(url, mealId);
  }

addMealToMealPlan Форма с использованием реактивных форм:

 <form [formGroup]="addMealToMealplanForm" 
  <div class="form-group">
    (ngSubmit)="addMealToMealplan()">
         <label for="meal">Meal</label>
        <select id="meal" formControlName="meal">
          <option *ngFor="let meal of meals" [ngValue]="meal" 
    [label]="meal.name"></option>
    </select>
  </div>
  <div class="form-group">
    <label for="weekday">Weekday</label>
    <select class="form-control" id="weekday" formControlName="weekday">
      <option *ngFor="let key of weekdayOptions" [value]="key" [label]="weekday[key]"></option>
    </select>
  </div>
  <button class="btn" type="submit">Add Meal to Mealplan</button>
</form>

1 Ответ

1 голос
/ 18 апреля 2020

вы не предоставили достаточно информации для определенного ответа, но вам нужно на самом деле создать объект MealPlan с new где-нибудь, чтобы использовать методы класса, такие как те, которые есть в наборе, в противном случае конструктор не и вы просто врете TypeScript о типе. TypeScript не создает автоматически объекты для вас просто путем приведения.

где-то в вашем коде, вам нужно либо:

 this.mealPlan = new MealPlan();
 // logic to populate properties

, либо если вы получаете начальное значение из вызова http: что-то вроде:

getMealPlan() {
  return this.http.get('mealplan.url.com').pipe(
    map(mpResponse => {
      const mp = new MealPlan();
      // logic to populate with response values
      return mp;
    })
  );
}

или вы можете инкапсулировать эти логики заполнения ответов c в своем конструкторе:

export class Mealplan {
  id: number;
  mealsPerWeek: Map<Weekday, Meal>;

  constructor(mealPlanResponse) {
    this.id = mealPlanResponse.id;
    this.mealsPerWeek = new Map();
    // logic to populate
  }
}

, чтобы вы могли просто сделать

 map(mpResponse => new MealPlan(mpResponse))

ОДНАКО .... вы причиняете себе много боли и сложности, используя набор, и я не уверен, что вижу выгоду от предоставленного кода. Просто определите вашу еду как интерфейс и сделайте это:

export interface Mealplan {
  id: number;
  mealsPerWeek: {[key in Weekday]: Meal};
}

, тогда вам не нужно создавать какие-либо конструкции, и вы легко устанавливаете значения:

this.mealplan.mealsPerWeek[this.selectedWeekday.value] = this.selectedEssen.value;

Последнее примечание, если вы хотите разрешить частичное заполнение объекта mealsPerWeek в этом интерфейсе, как это было бы разрешено в наборе (IE только перечисление в понедельник), вам нужно объявить его как частичное:

mealsPerWeek: Partial<{[key in Weekday]: Meal}>;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...