【问题标题】:Angular 2 template updating but breaking click handlersAngular 2 模板更新但破坏了点击处理程序
【发布时间】:2017-05-17 12:14:29
【问题描述】:

我有一个处理单一类型对象的应用程序。我使用服务管理对象的状态。在一个组件中,我显示对象。从这里您可以单击字段以在另一个组件中对其进行编辑。您还可以单击按钮将新项目添加到字段并删除项目。

大多数情况下它工作正常,但有时它会在没有任何错误消息的情况下中断。我单击删除或编辑按钮或字段,但没有任何反应。单击处理程序已损坏(我已在控制台中检查过)。这通常发生在我从数组中添加或删除之后。

这很令人困惑,因为当我添加一个元素时,我使用 http 来确保它被保存到数据库中,然后只有在返回带有新液滴的 observable 之后,我才让角度更新显示。并且显示总是更新。然而,有时显示更新,但占卜没有意识到,这很奇怪。所以我会添加一个提示,例如提示会在数据库中可见,被返回并更新视图,但在组件中是看不到的。

这也是不一致的。有时工作得很好。

这是视图中的一些示例代码。

<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 更新视图中的数组有关,但索引未正确更新或单击处理程序正在中断,但这不仅仅是模板特定部分中的那些。我很茫然。

【问题讨论】:

    标签: angular ngfor


    【解决方案1】:

    *ngFor 指令中操作项目时,添加一个返回唯一索引的trackBy 函数非常重要,因此该指令可以在删除/添加项目时跟踪它们的属性。

    假设你的 tag.tag 是独一无二的,你可以这样写你的 *ngFor

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

    【讨论】:

    • 看来你现在在使用trackBy时需要使用一个函数,我已经这样做了,返回每个项目的id。但遗憾的是,它没有帮助。我也遇到了同样的问题。
    【解决方案2】:

    这个问题的解决方案很奇怪。我将组件与左侧显示的编辑表单并排放置,右侧显示正在编辑或创建的液滴。您可以单击右侧的按钮或字段,相应的表单将出现在左侧进行编辑。问题是,如果显示的液滴具有在右侧远远低于左侧组件的字段,则单击将无法正常工作,浏览器将简单地滚动到屏幕顶部。我不知道为什么会这样,但是在同一个视口中强制它解决了这个问题。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-08-27
      • 2016-05-02
      • 2018-03-31
      • 2016-11-13
      • 1970-01-01
      • 2014-12-13
      • 2011-08-31
      • 1970-01-01
      相关资源
      最近更新 更多