Angular 2 - Resolvido

20 respostas Resolvido
angular2
guilhermebhte

Último exemplo, https://material.angular.io/components/table/examples. Mas mudei para buscar da base de dados. As informações vem do banco de dados.

Sempre dá este erro:

EstadoComponent_Host.ngfactory.js? [sm]:1 ERROR TypeError: Cannot set property 'paginator' of undefined
    at EstadoComponent.ngAfterViewInit (estado.component.ts:44)
    at callProviderLifecycles (core.js:12706)
    at callElementProvidersLifecycles (core.js:12673)
    at callLifecycleHooksChildrenFirst (core.js:12656)
    at checkAndUpdateView (core.js:13811)
    at callViewAction (core.js:14153)
    at execEmbeddedViewsAction (core.js:14111)
    at checkAndUpdateView (core.js:13803)
    at callViewAction (core.js:14153)
    at execComponentViewsAction (core.js:14085)

Meu código

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

import { Http } from '@angular/http';
import { Router } from '@angular/router';

import {MatPaginator, MatSort, MatTableDataSource} from '@angular/material';
import { Estado } from '../model/estado.model';
import { EstadoService } from './estado.service';

@Component({
  selector: 'app-estado',
  templateUrl: './estado.component.html',
  styleUrls: ['./estado.component.css']
})
  export class EstadoComponent implements OnInit {
    //displayedColumns = ['id', 'name', 'progress', 'color'];
    displayedColumns = ['pais', 'descricao', 'sigla'];
    dataSource: MatTableDataSource<Estado>;
    
    //dataSource: MatTableDataSource<UserData>;
  
    @ViewChild(MatPaginator) paginator: MatPaginator;
    @ViewChild(MatSort) sort: MatSort;
      
    estados: Estado[];

    constructor(private router: Router, private estadoService : EstadoService) { }

    ngOnInit() {
     
      this.estadoService.todos().forEach(
      //subscribe( 
        (data :any) => { 
          this.estados = data.lista;
          this.dataSource = new MatTableDataSource(this.estados);
      });
    }
  
    /**
     * Set the paginator and sort after the view init since this component will
     * be able to query its view for the initialized paginator and sort.
     */
    ngAfterViewInit() {
      this.dataSource.paginator = this.paginator;
      this.dataSource.sort = this.sort;
    }
  
    applyFilter(filterValue: string) {
      filterValue = filterValue.trim(); // Remove whitespace
      filterValue = filterValue.toLowerCase(); // Datasource defaults to lowercase matches
      this.dataSource.filter = filterValue;
    }
  }
  
  /** Builds and returns a new User. */
  function createNewUser(id: number): UserData {
    const name =
        NAMES[Math.round(Math.random() * (NAMES.length - 1))] + ' ' +
        NAMES[Math.round(Math.random() * (NAMES.length - 1))].charAt(0) + '.';
  
    return {
      id: id.toString(),
      name: name,
      progress: Math.round(Math.random() * 100).toString(),
      color: COLORS[Math.round(Math.random() * (COLORS.length - 1))]
    };
  }
  
  /** Constants used to fill up our data base. */
  const COLORS = ['maroon', 'red', 'orange', 'yellow', 'olive', 'green', 'purple',
    'fuchsia', 'lime', 'teal', 'aqua', 'blue', 'navy', 'black', 'gray'];
  const NAMES = ['Maia', 'Asher', 'Olivia', 'Atticus', 'Amelia', 'Jack',
    'Charlotte', 'Theodore', 'Isla', 'Oliver', 'Isabella', 'Jasper',
    'Cora', 'Levi', 'Violet', 'Arthur', 'Mia', 'Thomas', 'Elizabeth'];
  
  export interface UserData {
    id: string;
    name: string;
    progress: string;
    color: string;
  }

  function buscarEstado() {
    var i : number;
    i = 0;
    this.estadoService.todos().subscribe( 
      (data :any) => { 
        this.estados = data.lista;
    });

  }

20 Respostas

darlan_machado

Onde você criou/instanciou o atributo dataSource?

guilhermebhte

Entendo que aqui dataSource: MatTableDataSource;

darlan_machado

Isto é a declaração, você não instanciou este objeto, logo, o mesmo está nulo. Não existe, em nenhum lugar, o

new MatTableDataSource();

antes da linha em que o erro é disparado. Entendeu?

guilhermebhte

Não sei se vou conseguir te explicar.

Peguei o exemplo do site.

No exemplo a grade é populada por um array que é construído no momento da execução. No construtor, tem o for que monta o conteúdo para a tabela for (let i = 1; i <= 100; i++) { users.push(createNewUser(i)); }

No meu caso ele vai no banco de dados, o que faz correto, faz a consulta no Servidor JAVA, retorna as informações, monta a tabela, mas não tem paginação.

Não pesquisa e nem altera a quantidade de páginas, conforme imagem

Pois quando ele entra nestes métodos/funções, this.dataSource é nulo ou vazio.

ngAfterViewInit() {
        this.dataSource.paginator = this.paginator;
        this.dataSource.sort = this.sort;
      }

      applyFilter(filterValue: string) {
        filterValue = filterValue.trim(); // Remove whitespace
        filterValue = filterValue.toLowerCase(); // Datasource defaults to lowercase matches
        this.dataSource.filter = filterValue;
      }

No construtor aonde ele faz requisição ao servidor, ele deveria espera o retorno, para depois renderizar a tela e preencher as variáveis.

Conseguiu entender ?

Segue o exemplo do site

import {Component, ViewChild} from '@angular/core';
import {MatPaginator, MatSort, MatTableDataSource} from '@angular/material';

/**
 * @title Data table with sorting, pagination, and filtering.
 */
@Component({
  selector: 'table-overview-example',
  styleUrls: ['table-overview-example.css'],
  templateUrl: 'table-overview-example.html',
})
export class TableOverviewExample {
  displayedColumns = ['id', 'name', 'progress', 'color'];
  dataSource: MatTableDataSource<UserData>;

  @ViewChild(MatPaginator) paginator: MatPaginator;
  @ViewChild(MatSort) sort: MatSort;

  constructor() {
    // Create 100 users
    const users: UserData[] = [];
    for (let i = 1; i <= 100; i++) { users.push(createNewUser(i)); }

    // Assign the data to the data source for the table to render
    this.dataSource = new MatTableDataSource(users);
  }

  /**
   * Set the paginator and sort after the view init since this component will
   * be able to query its view for the initialized paginator and sort.
   */
  ngAfterViewInit() {
    this.dataSource.paginator = this.paginator;
    this.dataSource.sort = this.sort;
  }

  applyFilter(filterValue: string) {
    filterValue = filterValue.trim(); // Remove whitespace
    filterValue = filterValue.toLowerCase(); // Datasource defaults to lowercase matches
    this.dataSource.filter = filterValue;
  }
}

/** Builds and returns a new User. */
function createNewUser(id: number): UserData {
  const name =
      NAMES[Math.round(Math.random() * (NAMES.length - 1))] + ' ' +
      NAMES[Math.round(Math.random() * (NAMES.length - 1))].charAt(0) + '.';

  return {
    id: id.toString(),
    name: name,
    progress: Math.round(Math.random() * 100).toString(),
    color: COLORS[Math.round(Math.random() * (COLORS.length - 1))]
  };
}

/** Constants used to fill up our data base. */
const COLORS = ['maroon', 'red', 'orange', 'yellow', 'olive', 'green', 'purple',
  'fuchsia', 'lime', 'teal', 'aqua', 'blue', 'navy', 'black', 'gray'];
const NAMES = ['Maia', 'Asher', 'Olivia', 'Atticus', 'Amelia', 'Jack',
  'Charlotte', 'Theodore', 'Isla', 'Oliver', 'Isabella', 'Jasper',
  'Cora', 'Levi', 'Violet', 'Arthur', 'Mia', 'Thomas', 'Elizabeth'];

export interface UserData {
  id: string;
  name: string;
  progress: string;
  color: string;
}
darlan_machado

Sim, eu entendi.
Você que não entendeu que você nunca instanciou o dataSource.

ngAfterViewInit() {
    this.dataSouce = new MatTableDataSource();//Esta linha que falta
    this.dataSource.paginator = this.paginator;
    this.dataSource.sort = this.sort;
}
guilhermebhte

Entendi, mas é porque no exemplo do site não está assim…

Alterado o erro continua e deu outro erro:

ERROR in src/app/estado/estado.component.ts(46,12): error TS2551: Property ‘dataSouce’ does not exist on type ‘EstadoComponent’. Did you mean ‘dataSource’?

Segue imagens

C

this.dataSouce = new MatTableDataSource();
dataSouce está escrito incorretamente. Tente colocar this.dataSource.

darlan_machado

Não, o erro diz que você esqueceu de escrever o nome corretamente. Você escreveu

this.dataSouce

Quando deveria escrever

this.dataSource
guilhermebhte

Sim, estou cego kkkk.

Mas de qualquer maneira não funciona e o erro continua.

darlan_machado

Cara, o mesmo erro? Tem certeza?

guilhermebhte

Percebi que tinha colocado esta instrução this.dataSouce = new MatTableDataSource();//Esta linha que falta, no local errado.

Na verdade não tem erro no console, mas ele não tem o resultado.
Quando entro na página, ele ainda não carregou a informação no banco de dados e por isto não tem resultado neste momento, conforme imagem.

darlan_machado

Fora ter instanciado em local errado, você chegou a debugar para ver se os dados estão sendo retornados pelo serviço?

guilhermebhte

Como disse, na inicialização deste componente do angular, os dados ainda não foram buscados do banco de dados, conforme imagem anterior.

Primeiro ele carrega o componente MatTableDataSource no metodo ngAfterViewInit(). depois ele consulta a base de dados no método ngOnInit. Deveria ser ao contrário.

darlan_machado

Tem certeza? Cara, after é depois…

guilhermebhte

Tenho certeza, quando ele chega nesta linha, está vazio, conforme imagem.

Inclusive this.dataSource.sort = this.sort;, aqui o this.sorte está undefined

darlan_machado

Que está vazio eu não duvido, o que eu não tenho certeza é que a ordem de acontecimentos é afterView ou oninit.

guilhermebhte

Entrei na tela. Tem dois breackpoints conforme imagem.

Os breackpoints estão nas linhas 32 e 37.

primeiro ele para na linha 37, aonde está o método ngAfterViewInit, e depois ele vai para a linha 37, aonde faz a consulta com o banco de dados no método ngOnInit.

Entendeu ?

darlan_machado

Certo, e por que ele não trouxe os dados necessários?

guilhermebhte

Porque na primeira vez que ele para no breakpoint ele não foi ao banco de dados ainda.

Somente na 2ª vez. Ai a variável this.dataSource está vazia

Acho que vc não entendeu.

guilhermebhte
Solucao aceita

Consegui resolver:

import { Component, OnInit, ViewChild } from '@angular/core';
import { Router } from '@angular/router';

import { Pais } from '../modelo/pais.model';
import { PaisService } from './pais.service';

import {MatTableDataSource, MatPaginator} from '@angular/material';

@Component({
  moduleId: module.id,
  selector: 'app-pais',
  templateUrl: './pais.component.html',
  styleUrls: ['./pais.component.css'],
  providers: [PaisService]
})
export class PaisComponent implements OnInit {
  displayedColumns = ['descricao'];

  dataSource: MatTableDataSource<Pais>;

  paises: Pais[]; 

  @ViewChild(MatPaginator) paginator: MatPaginator;

  constructor(
      private router: Router, 
      private paisService: PaisService
    ) { }

  ngOnInit(): void {
    this.getPaises();
  }

  getPaises(): void {
    this.paisService.getPaises().subscribe( 
      (data :any) => { 
      this.dataSource = new MatTableDataSource<Pais>(data);
      this.dataSource.paginator = this.paginator;
    });

  }

  alterar(pais: Pais){
    console.log(pais);
    console.log("Alterando país ");
    this.router.navigate(['/pais/alterar/' + pais.id]);
  }
}
Criado 22 de março de 2018
Ultima resposta 4 de abr. de 2018
Respostas 20
Participantes 3