Angular не может прочитать свойство undefined в компоненте / форме - PullRequest
0 голосов
/ 07 мая 2018

Я пытаюсь заставить UPDATE работать с моим CRUD API. Я знаю, что проблема в форме или компоненте для ОБНОВЛЕНИЯ, но я не уверен, что мне не хватает.

Форма HTML

<form #form="ngForm" (ngSubmit)="updateReminder(form.value)">
  <div class="form-group">
    <label for="nameField">Name:</label>
    <input name="nameField" class="form-control" [ngModel]="reminders.name">
    <br />
    <label for="occasionField">Occasion:</label>
    <input name="occasionField" class="form-control" 
[ngModel]="reminders.occasion">
 </div>
 <button type="submit">save</button>
</form>

Компонент формы

import { Component, OnInit, Input } from '@angular/core';
import { ReminderService } from '../providers/reminder.service';

@Component({
  selector: 'app-results',
  templateUrl: './results.component.html',
  styleUrls: ['./results.component.css'],
  providers: [ReminderService]

})
export class ResultsComponent implements OnInit {

constructor(private reminderService:ReminderService) {}

 reminderList = null;
 @Input() reminders; 


ngOnInit() {}   


updateReminder(obj:any):void {
 this.reminders.name = obj.nameField;
 this.reminders.occasion = obj.occasionField;
 this.reminderService.updateReminder(this.reminders._id, this.reminders)
  .subscribe((result) =>{
    location.reload();
 })
}

Компонент приложения HTML

<div class="container">
<app-intro title="{{title}}"></app-intro>
<app-form ></app-form>
<app-results *ngFor='let reminder of reminderList' [reminders]="reminder">
</app-results>
</div>
<script src="https://code.jquery.com/jquery-3.3.1.min.js" integrity="sha256- FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8=" crossorigin="anonymous"> 

Компонент приложения (маршрутизаторов нет)

import { Component } from '@angular/core';
import { ReminderService } from './providers/reminder.service';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css'],
  providers: [ReminderService]
})
export class AppComponent {

 title = 'The Amazing Reminder App';

  constructor(private reminderService:ReminderService) {}

  reminderList = null;

 ngOnInit() {
    this.reminderService.listReminders().subscribe((reminders)=>{
        this.reminderList = reminders;
    });
 } 
}

Ошибка в HTML:

ОШИБКА TypeError: Невозможно прочитать свойство 'name' из неопределенного

<input name="nameField" class="form-control" [ngModel]="reminders.name">

1 Ответ

0 голосов
/ 07 мая 2018

Проблема в том, что в качестве входной переменной объект reminders изначально не определен, пока angular не завершит инициализацию компонента. Смотрите эту строку прямо здесь.

@Input() reminders;

HTML-часть, однако, не ожидает рендеринга и поэтому пытается использовать эту переменную очень рано.

<input name="nameField" class="form-control" [ngModel]="reminders.name">

Поэтому, когда он пытается разрешить модель до того, как в процессе инициализации будет задана входная переменная, он попадает в неопределенную переменную и пытается найти в ней поле name, которое, конечно, еще не существует.

Существует несколько способов решения этой проблемы.

  1. присваивает объекту reminders значение по умолчанию, возможно, даже пустой объект. Я лично думаю, что таким образом вы жертвуете использованием памяти, чтобы предотвратить ошибки, которые кажутся нечистыми
  2. используйте оператор elvis в качестве пустой проверки в вашем html: [ngModel]="reminders?.name". Вы должны делать это в каждом поле, которое пытается получить доступ к полю объекта напоминания, в котором может быть много кода в зависимости от вашей формы
  3. отображает форму только когда объект напоминания наконец установлен. Это легко сделать с помощью простого *ngIf на окружающем элементе div или форме: <div class="form-group" *ngIf="reminders">

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

Есть еще вопросы по этой теме, например, вы можете проверить этот один прямо здесь.

Надеюсь, это поможет.


EDIT

Итак, я перепроверил ваш код, и хотя ваша функция updateReminder является отправкой формы, я думаю, что это чистая форма обновления. В этом случае я бы сказал, что вариант 3 должен работать нормально. Angular выполняет аккуратное обнаружение и повторное отображение изменений, поэтому вам, вероятно, следует сначала проверить, правильно ли установлена ​​входная переменная. Если да, angular должен сделать все остальное и перерисовать часть *ngIf в тот момент, когда он осознает, что объект существует сейчас.

Прежде чем мы проверяем входную переменную, всегда полезно понять, как угловые обрабатывают входные переменные, которые в конце концов сводятся к так называемым Lifecycle Hooks . Одним из специальных крючков является крючок ngOnInit(). Вот что говорит документация angular о крючке:

Инициализировать директиву / компонент после того, как Angular впервые отобразит привязанные к данным свойства и установит входные свойства директивы / компонента

В основном это означает, что переменные, переносимые в компонент как @Input, не устанавливаются при создании компонента (код конструктора), но только после его инициализации. Это приводит к некоторой задержке выполнения и в итоге к ошибке, которую вы указали выше.

Чтобы проверить, правильно ли установлена ​​входная переменная, мы можем просто зарегистрировать ее на консоли внутри ngOnInit().

ngOnInit() {
  console.log(this.reminders);
}  

Для сравнения, если вы сделаете это в конструкторе, вы увидите, что он все еще пуст на данный момент.

constructor(private reminderService:ReminderService) {
  // should be undefined at this point
  console.log(this.reminders);
}

Таким образом, если переменная напоминаний регистрируется из ngOnInit, подход *ngIf должен работать нормально.

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