Angular 2 - Resolvido

20 respostas Resolvido
angular2
G

Ú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

D

Onde você criou/instanciou o atributo dataSource?

G

Entendo que aqui dataSource: MatTableDataSource;

D

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?

G

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;
}
D

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;
}
G

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.

D

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

this.dataSouce

Quando deveria escrever

this.dataSource
G

Sim, estou cego kkkk.

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

D

Cara, o mesmo erro? Tem certeza?

G

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.

D

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

G

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.

D

Tem certeza? Cara, after é depois…

G

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

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

D

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

G

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 ?

D

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

G

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.

G
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