ERROR Typeerror: Cannot read Property 'id' of Undefined using mat-table

Asked

Viewed 580 times

0

It is giving this error when I add a new item, for my research I need to use an async, but the examples I found none use mat-table of angular material. I couldn’t apply it. How is an async done in this case?

Component:

import { Component, ElementRef, OnInit, ViewChild } from "@angular/core";
import { Router } from "@angular/router";
import { DataSource } from "@angular/cdk/collections";
import { HttpClient } from "@angular/common/http";
import { MatDialog, MatPaginator, MatSort } from "@angular/material";

import { Editorias } from "../models/editorias";
import { EditoriaEditarComponent } from "../editoria-editar/editoria-editar.component";
import { EditoriaCriarComponent } from "../editoria-criar/editoria-criar.component";
import { EditoriaType } from "../enum/editoria-type";
import { EditoriaService } from "../services/editoria.service";
import { AlertService } from "src/app/shared/services/alert.service";
import { DeleteDialogComponent } from "./dialogs/delete/delete-dialog/delete-dialog.component";

import { BehaviorSubject, fromEvent, merge, Observable } from "rxjs";
import { map } from "rxjs/operators";

@Component({
  selector: "app-editoria-listar",
  templateUrl: "./editoria-listar.component.html",
  styleUrls: ["./editoria-listar.component.scss"]
})
export class EditoriaListarComponent implements OnInit {
  displayedColumns = ["id", "name", "type", "actions"];
  editoriaDataBase: EditoriaService | null;
  dataSource: EditoriaDataSource | null;
  index: number;
  id: number;
  editoria: Editorias;
  value = "";

  constructor(
    public httpClient: HttpClient,
    public dialog: MatDialog,
    public dataService: EditoriaService,
    private alert: AlertService,
    private router: Router
  ) {

  }

  @ViewChild(MatPaginator) paginator: MatPaginator;
  @ViewChild(MatSort) sort: MatSort;
  @ViewChild("filter") filter: ElementRef;

  ngOnInit() {
    this.loadData();
  }

  refresh() {
    this.loadData();
  }

  addNew(editorias: Editorias) {
    const dialogRef = this.dialog.open(EditoriaCriarComponent, {
      data: { editorias: editorias }
    });

    dialogRef.afterClosed().subscribe(result => {
      if (result === 1) {
        // Depois de fechar o dialog atualiza as info no front
        // para add apenas empurra uma nova linha dentro do DataService
        this.editoriaDataBase.dataChange.value.push(
          this.dataService.getDialogData()
        );
        this.refreshTable();
      }
    });
  }

  // deleteEditoria(event) {
  //  // event.preventDefault();
  //  //this.id = id;
  //   let alertTitle = 'Excluir conta?',
  //     alertText = `Tem certeza que deseja excluir a conta "?`;

  //   this.alert.question(alertTitle, alertText, 'Confirmar', 'Cancelar')
  //     .then(
  //       () => {
  //         this.dataService.deleteEditoria(this.editoria.id)
  //           .subscribe(
  //             data => {
  //               alertTitle = 'Conta excluída!';
  //               alertText = `A conta  foi excluída.`;
  //               this.alert.success(alertTitle, alertText, 'Fechar')
  //                 .then(() => this.router.navigate(['/admin/editorias']));
  //             },
  //             err => {
  //               alertTitle = 'Erro ao excluir conta!';
  //              // alertText = `Não foi possível excluir a conta "${this.account.name}".`;
  //               this.alert.error(alertTitle, alertText, 'Fechar');
  //             }
  //           );
  //       },
  //       () => false
  //     );this.refreshTable();
  // }

  startEdit(i: number, id: number, name: string, type: EditoriaType) {

    this.id = id;
    this.index = i;
    console.log(this.index);
    const dialogRef = this.dialog.open(EditoriaEditarComponent, {
      data: { id: id, name: name, type: EditoriaType }
    });

    dialogRef.afterClosed().subscribe(result => {
      if (result === 1) {
        //  Ao usar uma edição as coisas são um pouco diferentes, primeiro encontramos um registro dentro do DataService por id
        const foundIndex = this.editoriaDataBase.dataChange.value.findIndex(
          x => x.id === this.id
        );
        // Em seguida, você atualiza esse registro usando dados de dialogData (valores inseridos)
        this.editoriaDataBase.dataChange.value[
          foundIndex
        ] = this.dataService.getDialogData();
        // E por último atualizar tabela
        this.refreshTable();
      }
    });
  }

  deleteItem(i: number, id: number, name: string, type: EditoriaType) {
    this.index = i;
    this.id = id;
    const dialogRef = this.dialog.open(DeleteDialogComponent, {
      data: { id: id, name: name, type: EditoriaType }
    });

    dialogRef.afterClosed().subscribe(result => {
      if (result === 1) {
        const foundIndex = this.editoriaDataBase.dataChange.value.findIndex(
          x => x.id === this.id
        );
        // Para excluir, usamos emenda para remover um único objeto do DataService
        this.editoriaDataBase.dataChange.value.splice(foundIndex, 1);
        this.refreshTable();
      }
    });
  }

  private refreshTable() {
    this.paginator._changePageSize(this.paginator.pageSize);
  }


  public loadData() {
    this.editoriaDataBase = new EditoriaService(this.httpClient);
    this.dataSource = new EditoriaDataSource(
      this.editoriaDataBase,
      this.paginator,
      this.sort
    );
    fromEvent(this.filter.nativeElement, "keyup")
      // .debounceTime(150)
      // .distinctUntilChanged()
      .subscribe(() => {
        if (!this.dataSource) {
          return;
        }
        this.dataSource.filter = this.filter.nativeElement.value;
      });
  }
}

export class EditoriaDataSource extends DataSource<Editorias> {
  _filterChange = new BehaviorSubject("");

  get filter(): string {
    return this._filterChange.value;
  }

  set filter(filter: string) {
    this._filterChange.next(filter);
  }

  filteredData: Editorias[] = [];
  renderedData: Editorias[] = [];

  constructor(
    public _editoriaDataBase: EditoriaService,
    public _paginator: MatPaginator,
    public _sort: MatSort
  ) {
    super();
    //Redefinir para a primeira página quando o usuário altera o filtro.
    this._filterChange.subscribe(() => (this._paginator.pageIndex = 0));
  }

  /**  Função Connect chamada pela tabela para recuperar um fluxo contendo os dados a serem renderizados. */
  connect(): Observable<Editorias[]> {
    //  Ouça as alterações nos dados de base, na classificação, na filtragem ou na paginação
    const displayDataChanges = [
      this._editoriaDataBase.dataChange,
      this._sort.sortChange,
      this._filterChange,
      this._paginator.page
    ];

    this._editoriaDataBase.getAllEditoria();

    return merge(...displayDataChanges).pipe(
      map(() => {
        // filtro dos dados
        this.filteredData = this._editoriaDataBase.data
          .slice()
          .filter((editorias: Editorias) => {
            const searchStr = (editorias.id + editorias.name).toLowerCase();
            return searchStr.indexOf(this.filter.toLowerCase()) !== -1;
          });

        // Ordenar dados filtrados
        const sortedData = this.sortData(this.filteredData.slice());

        // Pega a fatia da página dos dados classificados filtrados.
        const startIndex = this._paginator.pageIndex * this._paginator.pageSize;
        this.renderedData = sortedData.splice(
          startIndex,
          this._paginator.pageSize
        );
        return this.renderedData;
      })
    );
  }

  disconnect() {}

  sortData(data: Editorias[]): Editorias[] {
    if (!this._sort.active || this._sort.direction === "") {
      return data;
    }

    return data.sort((a, b) => {
      let propertyA: number | string = "";
      let propertyB: number | string = "";

      switch (this._sort.active) {
        case "id":
          [propertyA, propertyB] = [a.id, b.id];
          break;
        case "name":
          [propertyA, propertyB] = [a.name, b.name];
          break;
      }

      const valueA = isNaN(+propertyA) ? propertyA : +propertyA;
      const valueB = isNaN(+propertyB) ? propertyB : +propertyB;

      return (
        (valueA < valueB ? -1 : 1) * (this._sort.direction === "asc" ? 1 : -1)
      );
    });
  }
}

Template:

<!-- .c-breadcrumb -->
<nav class="c-nav u-margin-top-none">
  <ol class="c-breadcrumb u-marginBottom-l">
    <li class="c-breadcrumb__item"><a [routerLink]="['/']">Home</a></li>
    <li class="c-breadcrumb__item">
      <i class="fas fa-caret-right"></i
      ><a [routerLink]="['/programacao']"> Editorias </a>
    </li>
    <li class="c-breadcrumb__item is-active">
      <i class="fas fa-caret-right"></i> Lista de Editorias
    </li>
  </ol>
</nav>
<!-- // .c-breadcrumb -->

<!-- <caption class="caption__title">
    Lista de editorias
  </caption> -->

<mat-toolbar>
  <span class="spacer"></span> Atualizar:
  <button mat-icon-button (click)="refresh()">
    <mat-icon>refresh</mat-icon>
  </button>
</mat-toolbar>

<div class="container mat-elevation-z8">
  <div class="form">
    <mat-form-field floatPlaceholder="never">
      <input
        matInput
        #filter
        placeholder="Buscar Editoria"
        type="text"
        [(ngModel)]="value"
      />
      <button
        mat-button
        *ngIf="value"
        matSuffix
        mat-icon-button
        aria-label="Clear"
        (click)="value = ''"
      >
        <mat-icon>close</mat-icon>
      </button>
    </mat-form-field>
  </div>

  <mat-table #table [dataSource]="dataSource" matSort class="mat-cell">
    <!--- Note that these columns can be defined in any order.
            The actual rendered columns are set as a property on the row definition" -->

    <!-- ID Column -->
    <ng-container matColumnDef="id">
      <mat-header-cell *matHeaderCellDef mat-sort-header>Id</mat-header-cell>
      <mat-cell *matCellDef="let row">{{ row.id }}</mat-cell>
    </ng-container>

    <ng-container matColumnDef="name">
      <mat-header-cell *matHeaderCellDef mat-sort-header>Nome</mat-header-cell>
      <mat-cell *matCellDef="let row"> {{ row.name }}</mat-cell>
    </ng-container>
    <ng-container matColumnDef="type">
      <mat-header-cell *matHeaderCellDef mat-sort-header>Tipo</mat-header-cell>
      <mat-cell *matCellDef="let row"> {{ row.type }}</mat-cell>
    </ng-container>

    <!-- actions -->
    <ng-container matColumnDef="actions">
      <mat-header-cell *matHeaderCellDef>
        <!-- <button mat-icon-button class="btn-acessar u-text-uppercase u-text-bold" color="primary" (click)="addNew()"> Nova Editoria
          <mat-icon aria-label="Example icon-button with a heart icon"
            >add</mat-icon
          >
        </button> -->
        <button mat-raised-button (click)="addNew()">Nova Editoria</button>
      </mat-header-cell>

      <mat-cell *matCellDef="let row; let i = index">
        <button
          mat-icon-button
          (click)="startEdit(i, row.id, row.name, row.type)"
        >
          Editar
          <mat-icon aria-label="Edit">edit</mat-icon>
        </button>

        <button
          mat-icon-button
          (click)="deleteItem(i, row.id, row.name, row.type)"
        >
          Excluir
          <mat-icon aria-label="Delete">delete</mat-icon>
        </button>
      </mat-cell>
    </ng-container>

    <mat-header-row *matHeaderRowDef="displayedColumns"></mat-header-row>
    <mat-row *matRowDef="let row; columns: displayedColumns"></mat-row>
  </mat-table>

  <div
    class="no-results"
    [style.display]="dataSource.renderedData.length == 0 ? '' : 'none'"
  >
    Nenhum Resultado Encontrado.
  </div>

  <mat-paginator
    #paginator
    [length]="dataSource.filteredData.length"
    [pageIndex]="0"
    [pageSize]="10"
    [pageSizeOptions]="[5, 10, 25, 100]"
  >
  </mat-paginator>
</div>

Service:

import { Injectable } from "@angular/core";
import { BehaviorSubject } from "rxjs";
import { HttpClient, HttpErrorResponse } from "@angular/common/http";
import { Editorias } from "../models/editorias";

@Injectable({
  providedIn: "root"
})
export class EditoriaService {
  private readonly API_URL_Ed =
    "http://apihml/editorias/";
  dataChange: BehaviorSubject<Editorias[]> = new BehaviorSubject<Editorias[]>(
    []
  );

  dialogData: any;

  constructor(private httpClient: HttpClient) {}

  get data(): Editorias[] {
    return this.dataChange.value;
  }

  getDialogData() {
    return this.dialogData;
  }

  /** CRUD METHODS */
  getAllEditoria(): void {
    this.httpClient.get<Editorias[]>(this.API_URL_Ed).subscribe(
      data => {
        this.dataChange.next(data);
      },
      (error: HttpErrorResponse) => {
        console.log(error.name + " " + error.message);
      }
    );
  }

  // addEditorias(editorias: Editorias): void {
  //   this.dialogData = editorias;
  // }

  // ADD, POST METHOD
  addEditorias(editorias: Editorias): void {
    this.httpClient.post(this.API_URL_Ed, editorias).subscribe(
      data => {
        this.dialogData = editorias;
      },
      (err: HttpErrorResponse) => {}
    );
  }

  // updateEditoria(editorias: Editorias): void {
  //   this.dialogData = editorias;
  // }

  // UPDATE, PUT METHOD
  updateEditoria(editorias: Editorias): void {
    this.httpClient.put(this.API_URL_Ed + editorias.id, editorias).subscribe(
      data => {
        this.dialogData = editorias;
      },
      (err: HttpErrorResponse) => {}
    );
  }

  // DELETE METHOD
  deleteItem(id: number): void {
    this.httpClient.delete(this.API_URL_Ed + id).subscribe(
      data => {
        console.log(data[""]);
        //this.toasterService.showToaster('Successfully deleted', 3000);
      },
      (err: HttpErrorResponse) => {
        //this.toasterService.showToaster('Error occurred. Details: ' + err.name + ' ' + err.message, 8000);
      }
    );
  }
}
  • What is the line of error?

  • async getAsyncData() { this.asyncResult = await this.httpClient.get<Employee>(this.url). toPromise(); console.log('No issues, I will Wait until Promise is resolved.'); }

  • @Guilhermecostamilam in this line: const searchStr = (editorias.id + editorias.name). toLowerCase();

  • @Guilhermecostamilam knows how I solve?

  • try this https://pastebin.com/GXZTVCb2 (includes async/await in anonymous method)

  • @Gaspar gave this error: [ts] The type 'Observable<Promise<Editorias[]>>' cannot be attributed to the type 'Observable<Editorias[]>'. The type 'Promise<Editorias[]>' cannot be assigned to the type 'Editorias[]'. The length property is missing in type 'Promise<Editorias[]>'. [2322]

  • @When I changed the code for what you went through, you know how I can fix it?

  • can paste stackTrace? the error that occurs?

Show 3 more comments
No answers

Browser other questions tagged

You are not signed in. Login or sign up in order to post.