在渲染Bootstrap模式之前,在Angular 2/4中重置变量

时间:2017-10-18 21:25:35

标签: twitter-bootstrap angular typescript bootstrap-modal bootstrap-4

所以我注意到我的引导模态与Angular 4结合起来非常奇怪的效果,先前打开的图像首先弹出,然后从我的图库中加载新选择的图像。原因是我的详细信息变量的值仍然使用上一个(点击)事件中的旧值填充。我可以在我的控制台日志中验证这一点。我的问题是如何在给出新值之前在 getArtworkDetail()方法中重置此变量?

我尝试将其设置为

this.details = undefined;

this.details = null;

但似乎根本没有注册该值,而是阻止模态加载。我的同事说这是由于TypeScript的单线程性质,但我对这个主题的研究很短,所以我希望在这里提供一些帮助。很有责任!

index.component.html

<!--SEARCH-->

<div class="input-group">
  <input #myInput
         [(ngModel)]="searchTerm"
         type="text"
         class="form-control"
         placeholder="Search artist or artwork..."
         (keyup.enter)="search()"/>
  <span class="input-group-btn">
    <button #myBtn
            (click)="search()"
            class="btn btn-default"
            type="button">Go!
    </button>
  </span>
</div>

<!--INDEX-->

<div class="row"
     *ngIf="hasArtPieces">
  <div *ngFor="let artwork of artworks"
       class="col-md-3 col-xs-12 centered">
    <div class="card">
      <a (click)="getArtworkDetail(artwork.id)"
         data-toggle="modal"
         data-target="#myModal">
        <img class="img-fluid thumb-img"
             src="{{artwork.url}}"
             alt="Thumbnail">
      </a>
      <div class="card-block">
        <p style="text-align: center"
           *ngIf="artwork.title.length < 20; then show else hide">
        </p>
        <ng-template #show>{{artwork.title }}</ng-template>
        <ng-template #hide>{{artwork.title.substring(0,20)}}...</ng-template>
      </div>
    </div>
    <br>
  </div>
</div>

<!--DETAIL-->

<div *ngIf="details"
     class="modal fade"
     id="myModal" tabindex="-1"
     role="dialog"
     aria-labelledby="myModalLabel">
  <div class="modal-dialog"
       role="document">
    <div class="modal-content">
      <div class="modal-header">
        <button type="button"
                class="close"
                data-dismiss="modal"
                aria-label="Close">
          <span aria-hidden="true">&times;</span>
        </button>
      </div>
      <div class="modal-body">
        <h1>{{details.title}}</h1>
        <h3>{{details.artist}}</h3>
        <img class="img-fluid" src="{{details.url}}"
             alt=""><br><br>
        <p>{{details.description}}</p>
      </div>
      <div class="modal-footer">
        <button type="button"
                class="btn btn-default"
                data-dismiss="modal">Close
        </button>
      </div>
    </div>
  </div>
</div>

index.component.ts

// imports emitted    

@Component({
  selector: 'artwork-index',
  templateUrl: './index.component.html',
  styleUrls: ['./index.component.css']
})


export class IndexComponent implements OnInit {
  artworks: ArtworkModel[];
  searchTerm: string;
  details: ArtworkDetailModel;
  hasArtPieces = false;

  constructor(private detailService: ArtworkDetailsService, private artworksService: ArtworksService) {
  }

  search() {
    if (this.searchTerm) {
      this.searchArtworks(this.searchTerm);
    }
  }

  searchArtworks(keyword) {
    this.artworksService.searchArtworks(keyword)
      .subscribe((artworkData: ArtworkModel[]) => {
          this.artworks = artworkData;
          this.hasArtPieces = true;
        }, err => console.log(err),
        () => console.log('Getting artworks complete...'));
  }

  getArtworkDetail(id) {
    this.detailService.getArtworkDetail(id)
      .subscribe((detailData: ArtworkDetailModel) => {
          this.details = detailData;
        }, err => console.log(err),
        () => console.log('Getting details complete...'));
  }

  ngOnInit() {
    this.searchArtworks('Rembrandt');
  }
}

2 个答案:

答案 0 :(得分:2)

似乎正在发生的事情是data-toggle="modal"锚元素(带(click)="getArtworkDetail(artwork.id)")在完成对艺术品详细信息的请求之前触发模态。

尝试以下两件事:

  1. 从模态div中删除*ngIf="details"指令。相反,将*ngIf="details"放在内部元素上 - 可能是.modal-body元素或该元素内部的容器div。
    • 这将允许缩略图按钮触发模态而无需等待加载艺术品细节
  2. this.details = null;添加回getArtworkDetail作为该函数的第一行。这将清除所有旧的详细信息,因为正在加载新的详细信息。
  3. 您可能希望显示一个微调器,直到该请求在某个时刻完成。在这种情况下,您可以使用*ngIf="details"指令在details值为空时提供微调器:*ngIf="details; else spinner"

    您的同事提到的单线程特性实际上是关于JavaScript而不是TypeScript,因为TypeScript在执行之前被编译为JavaScript。 JavaScript有效地作为单线程事件循环运行(尽管这不是guaranteed),但是从这些事件触发的某些任务可能是异步发生的。一个这样的异步任务是XMLHttpRequest。由于这是异步发生的,因此脚本在尝试显示模式之前不必等待它完成,这就是您的问题所在。

答案 1 :(得分:1)

As Mike Hill pointed out 解决方案是将*ngIf添加到内部元素并设置我的this.details = null哪个不起作用,但this.details = undefined工作,所以它最终看起来像*ngifmodal-body上:

<强> index.component.html

...

<!--DETAIL-->

<div
  class="modal fade"
  id="myModal" tabindex="-1"
  role="dialog"
  aria-labelledby="myModalLabel">
  <div class="modal-dialog"
       role="document">
    <div class="modal-content">
      <div class="modal-header">
        <button type="button"
                class="close"
                data-dismiss="modal"
                aria-label="Close">
          <span aria-hidden="true">&times;</span>
        </button>
      </div>
      <div class="modal-body"
           *ngIf="details">
        <h1>{{details.title}}</h1>
        <h3>{{details.artist}}</h3>
        <img class="img-fluid" src="{{details.url}}"
             alt=""><br><br>
        <p>{{details.description}}</p>
      </div>
      <div class="modal-footer">
        <button type="button"
                class="btn btn-default"
                data-dismiss="modal">Close
        </button>
      </div>
    </div>
  </div>
</div>

<强> index.component.ts

...

  getArtworkDetail(id) {
    this.details = undefined;
    this.detailService.getArtworkDetail(id)
      .subscribe((detailData: ArtworkDetailModel) => {
          this.details = detailData;
        }, err => console.log(err),
        () => console.log('Getting details complete...'));
  }