2017-01-03 2 views
1

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

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

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

Это также противоречиво. Иногда работает отлично.

Вот несколько примеров кода с точки зрения.

<h4>Hints (optional)</h4> 
<button class="btn btn-sm" [routerLink]="['/create/create5']">Add New</button> 
<div *ngIf="droplet.hints.length < 1">None</div> 
<div class="row" *ngFor="let hint of droplet.hints; let i=index"> 
    <div class="hint col-md-10" (click)="selectHint(i)"> 
    <span [innerHTML]="hint.content || empty"></span> 
    <span (click)="removeElement(i, 'hint')" class="pull-right glyphicon glyphicon-remove" aria-hidden="true"></span> 
    </div> 
</div> 

<h4>Tags 
    <div class="progress-marker" [class.complete]="droplet.tags.length > 0"></div> 
    <div class="progress-marker" [class.complete]="droplet.tags.length > 1"></div> 
    <div class="progress-marker" [class.complete]="droplet.tags.length > 2"></div> 
</h4> 
<button class="btn btn-sm" [routerLink]="['/create/create6']">Add New</button> 
<div *ngIf="droplet.tags.length < 1">None</div> 
<br> 
<button *ngFor="let tag of droplet.tags; let i=index" type="button" class="btn btn-default btn-sm" (click)="removeElement(i, 'tag')"> 
    <span class="glyphicon glyphicon-remove" aria-hidden="true"></span> {{ tag.tag }} 
</button> 

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

Соответствующий код компонента выглядит следующим образом:

import { Component, OnInit } from '@angular/core'; 
import { Droplet } from '../droplet'; 
import { DropletService } from '../droplet.service'; 
import { Router } from '@angular/router'; 
import { Subscription } from 'rxjs/Rx'; 
import { HttpService } from '../http.service'; 

export class ShowDropletComponent implements OnInit { 
    droplet: Droplet; 

    constructor(
    private dropletService: DropletService, 
    private router: Router, 
    private httpService: HttpService 
) { } 

    ngOnInit() { 
    this.droplet = this.dropletService.getCurrentDroplet(); 
    this.dropletService.pushedDroplet.subscribe(
     droplet => this.droplet = droplet 
    ) 
    } 

    //using dummy to ensure element not updated unless returned from server 
    removeElement(index, element) { 
    console.log("remove clicked"); 
    let dummy = this.droplet; 
    if (element === "explanation") { 
     this.router.navigate(['create/create3']); 
     dummy.explanations.splice(index, 1); 
    } else if (element === "question") { 
     this.router.navigate(['create/create4']); 
     dummy.questions.splice(index, 1); 
    } else if (element === "hint") { 
     this.router.navigate(['create/create5']); 
     dummy.hints.splice(index, 1); 
    } else if (element === "tag") { 
     dummy.tags.splice(index, 1); 
    } 
    this.httpService.saveDroplet(dummy) 
     .subscribe(
     (droplet: Droplet) => { 
      this.dropletService.updateCurrentDroplet(droplet); 
     } 
    ); 
    } 

    editThis(field) { 
    if (field === "description") { 
     this.router.navigate(['create/create2']); 
    } else if (field === "name") { 
     this.router.navigate(['create/create1']); 
    } 
    } 

    selectExplanation(index) { 
    console.log("select exp clicked"); 
    this.router.navigate(['create/create3', index]); 
    } 

    selectQuestion(index) { 
    console.log("rselect q clicked"); 
    this.router.navigate(['create/create4', index]); 
    } 

    selectHint(index) { 
    console.log("select hint clicked"); 
    this.router.navigate(['create/create5', index]); 
    } 

} 

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

ответ

1

При манипулировании элементами в директиве *ngFor важно добавить функцию trackBy, которая возвращает уникальный индекс - поэтому директива может отслеживать их свойство при удалении/добавлении элементов.

Предполагая, что ваш tag.tag уникален вы могли бы написать *ngFor как это вместо:

<button *ngFor="let tag of droplet.tags; let i=index; trackBy: tag.tag" type="button"... 
+0

Кажется, вам теперь нужно использовать функцию, когда вы используете trackBy, который я сделал, возвращая идентификатор каждого элемента. Но, к сожалению, это не помогает. Я испытываю те же проблемы. – Finnjon

0

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

Смежные вопросы