【问题标题】:Angular error Cannot read property 'style' of undefined角度错误无法读取未定义的属性“样式”
【发布时间】:2022-05-16 16:01:38
【问题描述】:

我正在尝试将 following slideshow 的 javascript 版本转换为在 Typescript 语言中使用,但我遇到了一个问题:

我收到一条错误消息:

无法读取未定义的属性“样式”

看起来它不接受打字稿中的slides[this.selectedindex - 1].style.display。所以我添加了(<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;
}

【问题讨论】:

    标签: angular typescript


    【解决方案1】:

    stackblitz link 中的工作演示

    您需要在 Angular 中引用 html 元素才能在 Angular 中进行 dom 操作。

    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=compress&cs=tinysrgb&dpr=1&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>
    

    上面的#slides 和#dots 是模板引用变量。我们正在使用 @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
    }
    

    【讨论】:

    • 哇,这很好用,唯一的问题是其中一些代码我以前从未见过。您删除了implements OnInit 并使用ngAfterViewInit 而不是ngOnInit。我注意到它给我带来了forEach 循环函数和ngOnInit 的错误。不确定slider$; 是否有任何作用。
    • 我们正在使用@ViewChildren().. 要获得此参考仅在ngAfterViewOnit() 中可用。此事件仅在组件视图由 Angular 渲染并且在组件文件中可用后触发。在 ngOnOnit() 中,我们无法获取组件内的任何视图元素。
    • 如果您还有任何疑问,请随时通过电子邮件与我联系:grdtechlab@gmail.com。
    【解决方案2】:

    您是否尝试过使用 viewChild 而不是 document.getElementByClassName。

    所以,将 html 中的 id 和 id 提供给您的幻灯片部分。

     <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 中使用了 custom-webpack。删除和使用默认构建配置很有帮助。

      "builder": "@angular-builders/custom-webpack:browser",

      "builder": "@angular-devkit/build-angular:browser",

      例如

      【讨论】:

        猜你喜欢
        • 2022-01-08
        • 2019-06-29
        • 2023-03-29
        • 2018-08-10
        • 2019-04-26
        • 1970-01-01
        • 1970-01-01
        • 2016-07-20
        • 1970-01-01
        相关资源
        最近更新 更多