为什么轮播实现CSS和* ngFor无法动态地协同工作以获取图像 [英] Why carousel of materialize css and *ngFor not working together dynamicaly to get images

查看:66
本文介绍了为什么轮播实现CSS和* ngFor无法动态地协同工作以获取图像的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试为轮播实现具体的角度代码.轮播与动态数组相关联,但是当我对轮播类使用 * ngFor 时,轮播不起作用.

I'm trying to materialize angular code for carousel. The carousel is associated to a dynamic array but when i use *ngFor with carousel class its not working.

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

I tried writing the class="carousel-item" inside for loop but console shows:

无法读取未定义的属性"clientWidth".

Cannot read property 'clientWidth' of undefined.

此代码不起作用:

模板:

<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循环并依次写< div class ="carousel-item"> 像:

I'm only getting one image that too which is cropped in half where as if i remove the for loop and write <div class="carousel-item"> one after the other like:

<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>

这样做,轮播工作了,但是它并没有绑定到我想要的动态数组上.

Doing this, I get the carousel working but it is not binded to a dynamic array which is what i want.

推荐答案

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

Instead of initialising the carousel in OnInit use the AfterViewInit lifecycle hook

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

此外,请像这样更改模板:

In addition change your template like this:

<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 将创建物化所需的结构.

*ngFor on the a-tag will create the structure required by materialize.

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

Using the index of the current element and a new array called 'hrefs', the href attribute is set individually for each a-tag.

请查看此 Stackblitz 作为工作示例.

Please checkout this Stackblitz for a working example.

带有API响应

现在(以及在OnInit内轮播初始化期间)出现错误无法读取未定义的属性'clientWidth',未定义",因为当时 M.Carousel.init(...)被称为HTML结构尚未完成.只要未定义 this.items ,就不会有 carousel-item 类的a-tag.

The error "Can not read property 'clientWidth' of undefined" appears now (as well as during the initialization of the carousel within OnInit), because at the time the M.Carousel.init (...) is called the HTML structure is not complete yet. As long as this.items is undefined, there are no a-tags with class carousel-item.

要变通解决此问题,必须延迟实现轮播的初始化,直到从服务器加载数据并且所有标签都通过 * ngFor 添加到DOM为止.

To work around the problem, the initialization of the materialize carousel must be delayed until the data is loaded from the server and all a-tags were added to the DOM by *ngFor.

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

编辑#2

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

I just realized that there is a better method: instead of setting a timeout on the initialization of the carousel, let the *ngFor trigger the init after it's done adding the last item to the DOM. To do so, change your html like this:

<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>

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

In your component you will only need the following now:

// 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 .

这篇关于为什么轮播实现CSS和* ngFor无法动态地协同工作以获取图像的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆