#angular #typescript
#угловой #typescript
Вопрос:
Я пытаюсь преобразовать версию следующего слайд-шоу на JavaScript для использования на языке Typescript, но столкнулся с проблемой:
Я получаю сообщение об ошибке, в котором говорится:
Не удается прочитать свойство ‘style’ неопределенного
Похоже, что оно не принимается slides[this.selectedindex - 1].style.display
в typescript. Итак, я добавил (<HtmlElement>...)
, но это не работает.
Я реализовал следующий код:
home.component.ts
import { Component, OnInit, ViewChild } from '@angular/core';
import { Router, ActivatedRoute } from '@angular/router';
import { NgbCarousel, NgbSlideEvent, NgbSlideEventSource } from '@ng-bootstrap/ng-bootstrap';
@Component({
selector: 'app-home',
templateUrl: './home.component.html',
styleUrls: ['./home.component.css'],
})
export class HomeComponent implements OnInit {
title: string;
description: string;
role: Number;
public selectedindex: number = 0;
public images = ['../../assets/images/healthimage1.png', '../../assets/images/healthimage2.jpg', '../../assets/images/healthimage3.jpg'];
selectImage(index: number) {
console.log("Index: " index);
this.selectedindex = index;
console.log("Selected Index: " this.selectedindex);
}
showSlides() {
let i;
let slides = document.getElementsByClassName("mySlides");
let dots = document.getElementsByClassName("dot");
for (i = 0; i < slides.length; i ) {
(<HTMLElement>slides[i]).style.display = "none";
}
this.selectedindex ;
if (this.selectedindex > slides.length) { this.selectedindex = 1 }
for (i = 0; i < dots.length; i ) {
dots[i].className = dots[i].className.replace(" active", "");
}
(<HTMLElement>slides[this.selectedindex - 1]).style.display = "block";
dots[this.selectedindex - 1].className = " active";
setTimeout(this.showSlides, 2000);
}
constructor(
private activatedRoute: ActivatedRoute,
private router: Router) {
this.role = 1;
}
ngOnInit() {
this.showSlides();
}
}
home.component.html
<div *ngIf="images">
<div class="mySlides slideshow-container">
<img *ngFor="let image of images; let i=index"
[src]="image"
[ngClass]="{'image-active': selectedindex == i}">
<div style="text-align:center; display:inline-block;" *ngFor="let dot of images; let i=index">
<span class="dot"
(click)="selectImage(i)"
[ngClass]="{'active': selectedindex == i}">
</span>
</div>
</div>
</div>
css:
.slideshow-container {
max-width: 1200px;
position: relative;
margin: auto;
text-align:center;
}
.slideshow-container img{
display: none;
}
.slideshow-container img.image-active {
display: block;
width: 100%;
}
/* The dots/indicators */
.dot {
cursor: pointer;
height: 15px;
width: 15px;
margin: 0 2px;
background-color: #bbb;
border-radius: 50%;
display: inline-block;
transition: background-color 0.6s ease;
}
.active, .dot:hover {
background-color: #717171;
}
Ответ №1:
рабочая демонстрация в этой ссылке stackblitz
Вам нужно ссылаться на html-элемент в angular, чтобы манипулировать dom в angular.
html-шаблон
<ng-container>
<h2>Automatic Slideshow</h2>
<p>Change image every 2 seconds:</p>
<div class="slideshow-container">
<div #slides class="mySlides fade">
<div class="numbertext">1 / 3</div>
<img src="https://images.pexels.com/photos/6027869/pexels-photo-6027869.jpeg" style="width:100%">
<div class="text">Caption Text</div>
</div>
<div #slides class="mySlides fade">
<div class="numbertext">2 / 3</div>
<img src="https://images.pexels.com/photos/3889926/pexels-photo-3889926.jpeg?auto=compressamp;cs=tinysrgbamp;dpr=1amp;w=500" style="width:100%">
<div class="text">Caption Two</div>
</div>
<div #slides class="mySlides fade">
<div class="numbertext">3 / 3</div>
<img src="https://images.pexels.com/photos/6027869/pexels-photo-6027869.jpeg" style="width:100%">
<div class="text">Caption Three</div>
</div>
</div>
<br>
<div style="text-align:center">
<span #dot class="dot"></span>
<span #dot class="dot"></span>
<span #dot class="dot"></span>
</div>
</ng-container>
выше #слайды и #точки являются ссылочной переменной шаблона. Мы используем @ViewChildren(), чтобы получить более одной ссылки на элементы слайдов и точек из файла component.ts
файл component.ts
slidesIndex = 0;
@ViewChildren("slides") slides: QueryList<ElementRef>;
@ViewChildren("dot") dots: QueryList<ElementRef>;
slider$;
ngAfterViewInit() {
this.showSlides();
}
showSlides() {
this.slides.forEach(
(slidesDiv: ElementRef) =>
(slidesDiv.nativeElement.style.display = "none")
);
this.slidesIndex = 1;
if (this.slidesIndex > this.slides.length) {
this.slidesIndex = 1;
}
this.dots.forEach(
dotsDiv =>
(dotsDiv.nativeElement.className = dotsDiv.nativeElement.className.replace(
" active",
""
))
);
this.slides.toArray()[this.slidesIndex - 1].nativeElement.style.display =
"block";
this.dots.toArray()[this.slidesIndex - 1].nativeElement.className =
" active";
setTimeout(() => {
this.showSlides();
}, 2000); // Change image every 2 seconds
}
Комментарии:
1. Вау, это отлично работает, единственная загвоздка в том, что часть этого кода я никогда раньше не видел. Вы удалили
implements OnInit
и использовалиngAfterViewInit
вместоngOnInit
. Я заметил, что он выдал мне ошибку для функцииforEach
цикла withngOnInit
. Не совсем уверен, что что-тоslider$;
делает.2. Мы используем
@ViewChildren()
.. Чтобы получить ссылку на это, доступно только вngAfterViewOnit()
. Это событие срабатывает только после того, как представление компонента отображается angular и доступно внутри файла компонента. В ngOnOnit() мы не можем получить какие-либо элементы представления внутри компонента.3. Если у вас есть какие-либо дополнительные вопросы, не стесняйтесь обращаться ко мне по электронной почте: grdtechlab@gmail.com .
Ответ №2:
Вы пробовали использовать ViewChild, а не document.getElementByClassName.
Итак, укажите и идентификатор в html для вашего раздела слайда.
<div class="mySlides slideshow-container" id="idSlides">
В вашем угловом компоненте вы определяете слайды как
@ViewChild('idSlides', { static: false })
slides: Slides;
Я думаю, значение slides не должно быть null или undefined .
Document.getElementById используется для Javascript, а не для angular
Ответ №3:
После перехода с Angular 12 на 13 у меня возникла аналогичная ошибка, потому что мы использовали пользовательский веб-пакет в angular.json. Помогло удаление и использование конфигурации сборки по умолчанию.
"builder": "@angular-builders/custom-webpack:browser",
Для
"builder": "@angular-devkit/build-angular:browser",
например