ngFor не показывает никаких данных - PullRequest
0 голосов
/ 17 сентября 2018

Я пытаюсь привязать некоторые данные к шаблону с помощью Angular 6, так что это ngOnInit:

ngOnInit() {
    this.sub = this.route.params.subscribe(params => {
        this.id = +params['id'];
    });
    let url = this.baseUrl + `/items/${this.id}`;
    this.httpClient.get(url).subscribe((data : Array<any>)=> {
        this.ItemToEdit = data;
    });
}

Вот шаблон:

<div *ngFor="let item of ItemToEdit?.results">
              <div class="col-sm-8 float-left">

                <mat-form-field> <input matInput
                  class="form-control" placeholder="Item name"
                  formControlName="name" id="ItemName" value='{{ item.name }}'>
                </mat-form-field>

              </div>
</div>

Переменная ItemToEdit выглядит следующим образом:

{
  "results": [
    {
      "alias": [
        "first"
      ], 
      "apps": [], 
      "description": "this is an item", 
      "id": 1, 
      "name": "item342"
    }
  ]
}

Итак, проблема в том, что когда я открываю шаблон (с помощью какой-то кнопки), HTML-код, имеющий директиву ngFor, не отображается (div, имеющий ngFor, становится пустым). Я не знаю, как показать данные ... переменная ItemToEdit имеет только одно значение (длина = 1), но так как она имеет вложенный массив с именем results, я показываю данные через цикл for. Когда я пытаюсь сделать что-то подобное внутри машинописи:

  this.loadedName = this.ItemToEdit.results[0].name;

Я получаю сообщение об ошибке ItemToEdit.results не определено

Есть идеи?

EDIT

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

Сервер периодически возвращает ответы, подобные этим, вместо ожидаемых результатов:

  • { "error": "(_mysql_exceptions.OperationalError) (2006, 'MySQL server has gone away') [SQL: 'SELECT .... }
  • { "error": "(_mysql_exceptions.ProgrammingError) (2014, \"Commands out of sync; you can't run this command now\") [SQL: 'SELECT ......" }

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

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

Ответы [ 4 ]

0 голосов
/ 18 сентября 2018

Предпочтительным решением будет использование async, как определено в ответе антуан-клавихо .

В качестве альтернативы, если ваш компонент (или родители) определены с использованием ChangeDetectionStrategy.OnPush, например:

@Component({
  selector: 'app-component',
  templateUrl: './config.component.html',
  changeDetection: ChangeDetectionStrategy.OnPush
})

... вы можете сказать Angular, что компонент должен быть обновлен, например:

constructor(
  private ref: ChangeDetectorRef, 
  private httpClient: HttpClient) {}

ngOnInit() {
  this.sub = this.route.params.subscribe(params => {
    this.id = +params['id'];
  });
  const url = this.baseUrl + `/items/${this.id}`;
  this.httpClient.get(url).subscribe((data: Array<any>)=> {
    this.ItemToEdit = data;
    this.ref.detectChanges();
  });
}
0 голосов
/ 17 сентября 2018
test: any = [];  
ngOnInit() {
        this.service.test().subscribe(res => {
          this.test = res.results;
        });

Html:

 <p *ngFor="let test of this.test">
   {{test.name}}
 </p>

если вам нужно привязать его к полю ввода, просто присвойте ему: [value]="test?.name"

обслуживание:

test(): Observable<any>{
return this.http.get(url);
}
0 голосов
/ 18 сентября 2018

Существующий метод ngOnInit имеет проблемы:

  1. Он читает this.id до того, как this.id сможет установить.
  2. Не обновляется this.ItemToEdit когда this.id изменяется.
  3. this.id может не совпадать с фактическим идентификатором загружаемых в данный момент данных.

Следующая предлагаемая реализация решает эти проблемы с помощью:

  1. ожидание получения идентификатора перед выполнением HTTP-запросов,
  2. только обновление this.id, когда данные доступны в this.ItemToEdit, и
  3. отмена любого ожидающего HTTP-запроса, еслиИдентификатор изменяется до того, как он будет заполнен.
ngOnInit() {
    let itemToEditID;
    const httpObservable = this.route.params.pipe(
        map(params => +params['id']),
        tap(newID => itemToEditID = newID),
        switchMap(newID => this.httpClient.get(`${this.baseUrl}/items/${newID}`))
    );
    this.sub = httpObservable.subscribe(data => {
        this.id = itemToEditID;
        this.ItemToEdit = data;
    });
}

Размещение {{ ItemToEdit | json }} где-нибудь в вашем шаблоне позволило вам проверить фактические выходные данные сервера, что позволило вам идентифицировать частые ошибки, поступающие с сервера.

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

В зависимости от ваших потребностей, вы можете вывести ошибку сервера наВаша страница, когда это происходит:

<div *ngIf="ItemToEdit?.error" class="danger">
    <h2>An error occurred while trying to retrieve item {{ id }}</h2>
    <p>{{ error }}</p>
</div>
<div *ngFor="let item of ItemToEdit?.results">
    <!-- ... -->
</div>
0 голосов
/ 17 сентября 2018

постарайтесь сохранить все ваши процессы в асинхронном

<div *ngFor="let item of (itemToEdit$ | async)">
    <div class="col-sm-8 float-left">

    <mat-form-field> <input matInput
      class="form-control" placeholder="Item name"
      formControlName="name" id="ItemName" value='{{ item.name }}'>
    </mat-form-field>

    </div>
</div>

в вашем компоненте:

private itemToEdit$: Observable<any>;

....

ngOnInit() {
    this.route.params.subscribe(params => {
        this.id = +params['id'];
        let url = this.baseUrl + `/items/${this.id}`;
        this.itemToEdit$ = this.httpClient.get(url).pipe(
          map(data => data['results'])
        );
    });
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...