【问题标题】:Why carousel of materialize css and *ngFor not working together dynamicaly to get images为什么物化 css 和 *ngFor 的轮播不能动态协同工作以获取图像
【发布时间】:2019-04-13 15:25:28
【问题描述】:

我正在尝试实现旋转木马的角码。轮播与动态数组相关联,但是当我将*ngFor 与轮播类一起使用时,它不起作用。

我尝试在 for 循环中编写 class="carousel-item",但控制台显示:

无法读取未定义的属性“clientWidth”。

此代码不起作用:

模板:

<div class="carousel carousel-slider">
    <div class="carousel-item" href="#one!">
       <div *ngFor ="let item of items;let i = index">
           <img src={{items[i]}}>
        </div>
    </div>
</div>

组件:

options = {fullWidth: false};

constructor(private http: HttpClient) {
}

ngOnInit() {
    var elems = document.querySelectorAll('.carousel');
    var instances = M.Carousel.init(elems, this.options);
}

我也只得到一张图像,它被裁剪成两半,好像我删除了 for 循环并一个接一个地写 &lt;div class="carousel-item"&gt;,例如:

<a class="carousel-item" href="#one!"><img src={{items[0]}}></a>
<a class="carousel-item" href="#two!"><img src={{items[1]}}></a>
<a class="carousel-item" href="#three!"><img src={{items[2]}}></a>

这样做,我让轮播开始工作,但它没有绑定到我想要的动态数组。

【问题讨论】:

  • 您应该尝试使您的动态模板匹配预期的静态结果。你可以试试这个:&lt;a class="carousel-item" *ngFor ="let item of items;let i = index" [href]="i"&gt; &lt;img src={{ item }}&gt; &lt;/a&gt;

标签: javascript angular typescript angular-material materialize


【解决方案1】:

使用 AfterViewInit 生命周期钩子,而不是在 OnInit 中初始化轮播

import { Component, OnInit, AfterViewInit } from '@angular/core';
// other imports

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit, AfterViewInit {
  // ...

  constructor(private http: HttpClient) {}

  ngOnInit() {}

  ngAfterViewInit() {
    var elems = document.querySelectorAll('.carousel');
    var instances = M.Carousel.init(elems, this.options);
  }
}

另外像这样改变你的模板:

<div class="carousel">
    <a class="carousel-item" href="#{{hrefs[i]}}!" *ngFor="let item of items;let i = index">
        <img src={{item}}/>
    </a>
</div>

a-tag 上的*ngFor 将创建materialize 所需的结构。

使用当前元素的索引和一个名为“hrefs”的新数组,为每个 a-tag 单独设置 href 属性。

请查看此Stackblitz 以获取工作示例。

编辑:使用 API 响应

现在出现错误“无法读取未定义的属性'clientWidth'”(以及在 OnInit 内轮播初始化期间),因为在调用 M.Carousel.init (...) 时 HTML 结构尚未完成。只要this.items 未定义,就没有carousel-item 类的a-tags。

要解决此问题,必须延迟物化轮播的初始化,直到从服务器加载数据并且所有 a-tags 都由 *ngFor 添加到 DOM。

// removed code because it wasn't the best solution..
// it's still in the Stackblitz as comment

编辑#2

我刚刚意识到有一个更好的方法:不是在轮播初始化时设置超时,而是让*ngFor 在完成将最后一项添加到 DOM 后触发 init。为此,请像这样更改您的 html:

<div class="carousel">
    <a class="carousel-item" href="#{{hrefs[i]}}!" *ngFor="let item of items;let i = index; let last = last">
        <img src={{item}}/>
    <ng-container *ngIf="last">{{initCarousel()}}</ng-container>
  </a>
</div>

在您的组件中,您现在只需要以下内容:

// imports
// ...

export class AppComponent implements OnInit {
  // ...

  ngOnInit() {
    // dummy api request
    this.fakeApiRequest().pipe(delay(2000)).subscribe((res) => {
      // parse api response
      this.items = res;
    });
  }

  initCarousel() {
    // timeout needed, otherwise navigation won't work.
    setTimeout(() => {
       let elems = document.querySelectorAll('.carousel');
       let instances = M.Carousel.init(elems, this.options);
    }, 100);
  }

  fakeApiRequest(): Observable<string[]> {
    return of(["https://picsum.photos/200/300?image=0", "https://picsum.photos/200/300?image=1", "https://picsum.photos/200/300?image=2", "https://picsum.photos/200/300?image=3", "https://picsum.photos/200/300?image=4"]);
  }
}

调整后的Stackblitz

【讨论】:

  • 您好,感谢您的回复,我正在使用 items 数组,该数组使用 subscribe 从 api 获取数据,它位于 ngOnInit 内部。您的代码有效,但我仍然遇到未定义的相同错误客户端宽度。我尝试在模板上使用带有 if 条件的布尔检查 showCarousel,然后轮播不会出现,但也不会显示错误 this.getItems().subscribe((res) => { this.response = res; this.response.forEach ((entry) => { if (entry.url && entry.description) { this.items.splice(0, 0, entry.url); this.showCarousel = true;}
  • @SurajSharma 请检查我编辑的答案现在是否可以解决您的问题。
  • @SurajSharma 我有另一个想法,请查看我修改后的答案。
  • 我尝试了你的两个代码,第二个代码就像一个魅力与数据加载主题和第三个变体图像出现但我无法滑动/移动轮播。第二个变体可以标记为我认为的解决方案。再次感谢@coreuter :)
  • @SurajSharma 我已经修复了第三个变体。它还需要setTimeout(查看最后一个 Stackblitz)。您必须通过单击答案左侧的复选标记来close your question自己。
猜你喜欢
  • 2022-11-02
  • 2021-01-07
  • 1970-01-01
  • 1970-01-01
  • 2019-11-17
  • 2018-10-15
  • 2019-10-09
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多