13
respostas

Criando e usando componente no angular 2

Criei este componente para mostrar mensagem de sucesso ou não.

import { Component } from '@angular/core';
    import { MatSnackBar } from '@angular/material';

    @Component({
      selector: 'app-snack-bar',
      templateUrl: './snack-bar.component.html',
      styleUrls: ['./snack-bar.component.css']
    })
    export class SnackBarComponent {

      snackBar: MatSnackBar

      constructor(

      ) {}

      openSnackBar(message: string, isOnline : boolean) {
        this.snackBar.open(message, undefined, 
          { duration: 3000, 
            panelClass: isOnline ? ["online", "onlineAction"] : "offline" }
          );
      }
    }

Para chamar estou fazendo assim:

 onSubmit(form){
          const snackBarComponent = SnackBarComponent;
          snackBarComponent.prototype.openSnackBar(dados.mensagem, true);
    }

Só que apresenta este erro no console do navegador:

ERROR TypeError: Cannot read property 'open' of undefined
    at Object.SnackBarComponent.openSnackBar (snack-bar.component.ts:18)
    at MunicipioFormComponent.onSubmit (municipio-form.component.ts:115)
    at Object.eval [as handleEvent] (MunicipioFormComponent.html:1)
    at handleEvent (core.js:13547)
    at callWithDebugContext (core.js:15056)
    at Object.debugHandleEvent [as handleEvent] (core.js:14643)
    at dispatchEvent (core.js:9962)
    at eval (core.js:12301)
    at SafeSubscriber.schedulerFn [as _next] (core.js:4343)
    at SafeSubscriber.__tryOrUnsub (Subscriber.js:243)
View_MunicipioFormComponent_0 @ MunicipioFormComponent.html:1
proxyClass @ compiler.js:14653
DebugContext_.logError @ core.js:14996
ErrorHandler.handleError @ core.js:1509
dispatchEvent @ core.js:9966
(anonymous) @ core.js:12301
schedulerFn @ core.js:4343
SafeSubscriber.__tryOrUnsub @ Subscriber.js:243
SafeSubscriber.next @ Subscriber.js:190
Subscriber._next @ Subscriber.js:131
Subscriber.next @ Subscriber.js:95
Subject.next @ Subject.js:56
EventEmitter.emit @ core.js:4311
NgForm.onSubmit @ forms.js:5762
(anonymous) @ MunicipioFormComponent.html:1
handleEvent @ core.js:13547
callWithDebugContext @ core.js:15056
debugHandleEvent @ core.js:14643
dispatchEvent @ core.js:9962
(anonymous) @ core.js:10587
(anonymous) @ platform-browser.js:2628
ZoneDelegate.invokeTask @ zone.js:421
onInvokeTask @ core.js:4740
ZoneDelegate.invokeTask @ zone.js:420
Zone.runTask @ zone.js:188
ZoneTask.invokeTask @ zone.js:496
invokeTask @ zone.js:1517
globalZoneAwareCallback @ zone.js:1543
MunicipioFormComponent.html:1 ERROR CONTEXT DebugContext_ {view: {…}, nodeIndex: 0, nodeDef: {…}, elDef: {…}, elView: {…}}

O que pode ser ?

13 respostas

Boa noite, Guilherme! Como vai?

Isso está acontecendo pq dentro do método openSnackBar() da classe SnackBarComponent, vc está tentando utilizar o atributo snackBar: MatSnackBar chamando o método open() sem nunca antes ter instanciado um objeto do tipo MatSnackBar.

Grande abraço e bons estudos!

Sim entendi, por causa que no erro tem a palavra undefined, isto é, tentando utilizar algo que está indefinido.

Para cada componente (formulário) que crio, tenho que utilizar este SnackBar.

Pensei em criar um geral e chamar quando necessário, que é em todos os formulários do projeto.

Hoje está assim, quando crio uma página de formulário e/ou pesquisa. No construtor do componente.

constructor(
    private snackBar: MatSnackBar
  ) {}

No método que preciso chamar o snak

this.openSnackBar(data.mensagem, false);

Metodo do snac

openSnackBar(message: string, isOnline : boolean) {
    this.snackBar.open(message, undefined, 
      { duration: 3000, 
        panelClass: isOnline ? ["online", "onlineAction"] : "offline" }
      );
  }

Ai fiz da mesma forma no componente que criei, mas mesmo assim não funcionou.

Mas aí já é outro problema! Tem que ver qual é a mensagem de erro nesse caso e tudo mais. Até pq como o caso é outro, possivelmente a causa seja outra tbm!

Sim, a mensagem de erro que apareceu no console do navegador, eu coloquei na primeira mensagem deste tópico.

Mas a mensagem que vc colocou é a que fala sobre o undefined e se refere ao cenário que vc apresentou no primeiro comentário. Agora vc apresentou um outro cenário, diferente do inicial!

É a mesma mensagem de erro que aparece nos dois cenários?

Acho que não expliquei direito

O segundo cenário é o atual que funciona, hoje. Eu quis dizer que para cada formulário tenho que fazer o cenário 2.

Tenho que fazer mais de 50 formulários de pesquisa e cadastro/alteração, e ação de exclusão.

Como entendi que o Angular, podemos construir componente genérico e os outros ir chamando este.

Quando fui fazer, deu o erro, que no qual pedi ajuda neste fórum

Entendeu ?

Sim, é isso mesmo! Vc pode construir um componente e usar em outros. Só que para isso vc precisa instanciar o seu componente que está utilizando em algum ponto do seu código e isso não está ocorrendo acarretando no problema que vc está tendo.

Exemplo prático:

No caso do primeiro código que vc postou aqui, se vc fizer isso já deve funcionar (supondo que todo o resto esteja correto):

export class SnackBarComponent {
     snackBar: MatSnackBar = new MatSnackBar();

     // restante do código omitido
}

Outra coisa que acabei de observar!

No seu componente (código do primeiro comentário) o construtor não recebe parâmetros.

constructor(

) {}

Já no construtor das páginas que existem hj, repare que o construtor recebe parâmetro!

constructor(
    private snackBar: MatSnackBar
) {}

Sendo assim, pelo que parece, o snackBar: MatSnackBar está sendo injetado pelo Angular. Como no seu componente vc não fez isso, o Angular não injeta nada e por isso vc tem o problema do undefined.

Sim, na verdade tentei com as duas maneiras.

Vou testar aqui e coloco o resultado.

Fiz assim:

import { Component } from '@angular/core';
import { MatSnackBar } from '@angular/material';

@Component({
  selector: 'app-snack-bar',
  templateUrl: './snack-bar.component.html',
  styleUrls: ['./snack-bar.component.css']
})
export class SnackBarComponent {



  constructor(
      private snackBar: MatSnackBar
  ) {}

  openSnackBar(message: string, isOnline : boolean) {
    this.snackBar.open(message, undefined, 
      { duration: 3000, 
        panelClass: isOnline ? ["online", "onlineAction"] : "offline" }
      );
  }
}

Chamo assim:

 onSubmit(form){
          const snackBarComponent = SnackBarComponent;
          snackBarComponent.prototype.openSnackBar(dados.mensagem, true);
    }

Mesmo erro ...

Guilherme, primeiro, no onSubmit(), vc deve instanciar um objeto do tipo SnackBarComponent (vc não faz isso nesse último código que vc postou) e depois chamar o método openSnackBar(), assim: snackBarComponent.openSnackBar(dados.mensagem, true); }

Sim, já tinha entendido isto e fiz isto.

Mas ele pede 5 parâmetros, e não consegui identificar ainda quais são e o que coloco.

A questão é que deu um problema no servidor e estamos tentando analisar aqui o que pode ser.

No arquivo está assim:

export declare class MatSnackBar {
    private _overlay;
    private _live;
    private _injector;
    private _breakpointObserver;
    private _parentSnackBar;
    /**
     * Reference to the current snack bar in the view *at this level* (in the Angular injector tree).
     * If there is a parent snack-bar service, all operations should delegate to that parent
     * via `_openedSnackBarRef`.
     */
    private _snackBarRefAtThisLevel;
    /** Reference to the currently opened snackbar at *any* level. */
    _openedSnackBarRef: MatSnackBarRef<any> | null;
    constructor(_overlay: Overlay, _live: LiveAnnouncer, _injector: Injector, _breakpointObserver: BreakpointObserver, _parentSnackBar: MatSnackBar);
    /**
     * Creates and dispatches a snack bar with a custom component for the content, removing any
     * currently opened snack bars.
     *
     * @param component Component to be instantiated.
     * @param config Extra configuration for the snack bar.
     */