在呈现Bootstrap模式之前重置Angular 2/4中的变量

问题描述:

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

我尝试设置它像

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'); 
    } 
} 

这似乎是发生了你的是,data-toggle="modal"锚元素((click)="getArtworkDetail(artwork.id)")触发器请求作品细节前的模式已完成。

尝试这两个东西:

  1. 从模态DIV取出*ngIf="details"指令。相反,将*ngIf="details"放在内部元素上 - 可能是.modal-body元素或该元素内部的容器div。
    • 这将允许缩略图按钮,触发模态,而不必等待艺术品细节加载
  2. 添加this.details = null;getArtworkDetail作为函数的第一行。随着新的详细信息正在加载,这将清除所有旧的详细信息。

您可能希望显示一个微调框,直到该请求在某个点完成为止。在这种情况下,您可以使用*ngIf="details"指令提供微调,而details值为空:*ngIf="details; else spinner"


单线程的性质,你的同事称实际上是关于JavaScript的,而不是打字稿,因为打字稿被执行之前编译为JavaScript。 JavaScript有效地作为单线程事件循环运行(尽管这不是guaranteed),但是由这些事件触发的某些任务可能会异步发生。一个这样的异步任务是XMLHttpRequest。由于这是异步发生的,因此脚本无需等待它完成,然后再尝试显示模态,这是您的问题所在。

+1

谢谢!这解决了我的问题:) –

As Mike Hill pointed out 的解决方案是将*ngIf添加到内部元件,并设置我的this.details = null,没有工作,但this.details = undefined工作,因此结束了与*ngifmodal-body看起来像这样:

指数.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...')); 
    }