Search code examples
htmlangulartypescriptviewchild

Is something wrong with Angular ViewChild?


@import '../../main-styles.scss';
.note-card-container {
  position: relative;
  background: white;
  border-radius: 5px;
  box-shadow: 0px 2px 15px 2px rgba(black, 0.068);
  transition: box-shadow 0.2s ease-out;
  margin-top: 35px;
  &:hover {
    cursor: pointer;
    box-shadow: 0px 0px 0px 4px rgba(black, 0.068);
    .x-button {
      opacity: 1;
      transform: scale(1);
      transition-delay: 0.35s;
    }
  }
  .note-card-content {
    padding: 25px;
    .note-card-title {
      font-size: 22px;
      font-weight: bold;
      color: $purple;
    }
    .note-card-body {
      position: relative;
      color: #555;
      max-height: 80px;
      overflow: hidden;
      .fade-out-truncation {
        position: absolute;
        pointer-events: none;
        bottom: 0;
        height: 50%;
        width: 100%;
        background: linear-gradient(to bottom, rgba(white, 0) 0%, rgba(white, 0.8) 50%, white 100%);
      }
    }
  }
}

.x-button {
  position: absolute;
  top: 12px;
  right: 12px;
  height: 34px;
  width: 34px;
  background-color: $light-red;
  background-image: url('../../assets/delete_icon.svg');
  background-repeat: no-repeat;
  background-position: center;
  border-radius: 4px;
  transition: opacity 0.2s ease-out, transform 0.2s ease-out;
  opacity: 0;
  transform: scale(0.35);
  &:hover {
    background-color: darken($light-red, 3%);
  }
  &:active {
    background-color: darken($light-red, 5%);
  }
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.7.5/angular.min.js"></script>
<div #container class="note-card-container">

  <div class="note-card-content">
    <h1 class="note-card-title">Title</h1>

    <div #bodyText class="note-card-body">
      <p> This is a test </p>
      <div #truncator class="fade-out-truncation"></div>
    </div>
  </div>
  <div class="x-button"></div>
</div>

and i have a .ts too:

import { Component, ElementRef, OnInit, Renderer2, ViewChild, ViewChildren, } from '@angular/core';

@Component({
  selector: 'app-note-card',
  templateUrl: './note-card.component.html',
  styleUrls: ['./note-card.component.scss']
})
export class NoteCardComponent implements OnInit {
  name = "Angular";

  @ViewChild('truncator', {static: true}) truncator: ElementRef<HTMLElement>;
  @ViewChild('bodyText') bodyText: ElementRef<HTMLElement>;

  constructor(private renderer: Renderer2) { }

  ngOnInit() {
    let style = window.getComputedStyle(this.bodyText.nativeElement, null);
    let viewableHeight = parseInt(style.getPropertyValue("height"),10);

    if (this.bodyText.nativeElement.scrollHeight > viewableHeight) {
        this.renderer.setStyle(this.truncator.nativeElement, 'display', 'block');

    }else{
      this.renderer.setStyle(this.truncator.nativeElement,'display', 'none');
    }
  }

}

Error: error TS2564: Property 'truncator' has no initializer and is not definitely assigned in the constructor.

And i rly don't know why... This is the easiest thing i ever seen before and its doesnt working.. At the component.html need mark up the html element with a #, than in the component.ts use this: @ViewChild('truncator', {static: true}) truncator: ElementRef; I tried it in several ways like truncator and like bodyText, but nothing... Its so annoying..

Than why truncator and the other one isn't working......


Solution

  • The typescript error is because of exactly what it says: "not definitely assigned in the constructor", which in Angular for @ViewChild is normal.

    You can add ! - Definite Assignment Assertion to inform typescript that it will not be null:

      @ViewChild('truncator', {static: true}) truncator!: ElementRef<HTMLElement>;
      @ViewChild('bodyText') bodyText!: ElementRef<HTMLElement>;