我正在尝试实现轮播的角度代码。轮播与动态数组相关联,但是当我将*ngFor
与轮播类一起使用时,它将无法正常工作。
我尝试在循环中编写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循环并一个接一个写<div class="carousel-item">
一样,
<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>
这样做,轮播工作了,但是它没有绑定到我想要的动态数组上。
答案 0 :(得分:2)
使用OnInit
生命周期挂钩代替在AfterViewInit
中初始化轮播
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标签上的 *ngFor
将创建物化所需的结构。
使用当前元素的索引和一个名为“ hrefs”的新数组,为每个a-tag分别设置href属性。
请查看此Stackblitz以获取工作示例。
编辑:带有API响应
现在(以及在OnInit中轮播初始化期间)出现错误“无法读取未定义的属性'clientWidth',未定义”,因为在调用M.Carousel.init (...)
时HTML结构不完整然而。只要未定义this.items
,就不会有carousel-item
类的a-tag。
要变通解决此问题,必须延迟实现转盘的初始化,直到从服务器加载数据并且所有*ngFor
将所有a-tag添加到DOM为止。
// removed code because it wasn't the best solution..
// it's still in the Stackblitz as comment
编辑#2
我刚刚意识到有一个更好的方法:不要在轮播的初始化上设置超时,而是在将最后一项添加到DOM之后,让*ngFor
触发初始化。为此,请像这样更改您的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。