【问题标题】:Resetting variable in Angular 2/4 before rendering Bootstrap modal在渲染 Bootstrap 模态之前在 Angular 2/4 中重置变量
【发布时间】:2018-03-30 21:05:19
【问题描述】:

所以我注意到我的引导模式与 Angular 4 结合使用时出现了一个非常奇怪的效果,在从我的图库中加载新选择的图像之前,之前打开的图像首先弹出。原因是我的 details 变量的值仍然填充了上一个(点击)事件的旧值。我可以在我的控制台日志中验证这一点。我的问题是如何在我的 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');
  }
}

【问题讨论】:

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


    【解决方案1】:

    在您看来,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,而不是 TypeScript,因为 TypeScript 在执行之前会被编译为 JavaScript。 JavaScript 有效地作为单线程事件循环运行(虽然这不是guaranteed),但是从这些事件触发的某些任务可能会异步发生。 XMLHttpRequest 就是一个这样的异步任务。由于这是异步发生的,因此脚本不必等待它完成即可尝试显示模式,这似乎是您的问题所在。

    【讨论】:

      【解决方案2】:

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

      【讨论】:

        猜你喜欢
        • 2017-11-11
        • 2021-07-20
        • 2023-03-23
        • 2018-02-08
        • 1970-01-01
        • 2020-05-12
        • 1970-01-01
        • 2017-03-12
        • 2022-01-15
        相关资源
        最近更新 更多