所以我注意到我的引导模态与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">×</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');
}
}
答案 0 :(得分:2)
似乎正在发生的事情是data-toggle="modal"
锚元素(带(click)="getArtworkDetail(artwork.id)"
)在完成对艺术品详细信息的请求之前触发模态。
尝试以下两件事:
*ngIf="details"
指令。相反,将*ngIf="details"
放在内部元素上 - 可能是.modal-body
元素或该元素内部的容器div。
this.details = null;
添加回getArtworkDetail
作为该函数的第一行。这将清除所有旧的详细信息,因为正在加载新的详细信息。您可能希望显示一个微调器,直到该请求在某个时刻完成。在这种情况下,您可以使用*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
工作,所以它最终看起来像*ngif
在modal-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">×</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...'));
}