5

I want to use the Material Design Lite snackbar in Angular 2.

I tried to get hold of the Element in my template as the following:

My template

 <test>
     <div id="child1"> child1 <div id="child2">
      <div id="child2"> child2 <div id="child2">
       <div id="toast_error"> Error message </div>
      </div>
     </div>
    </div>
</test>

In my component file

constructor(private el:ElementRef){}

ngOnInit(){
        this.show_error("something");
    }
show_error(err){
        var snackbarContainer = this.el.nativeElement.querySelector("#toast_error")
        var data = {
            message: 'Button color changed.',
            timeout: 2000,
            actionText: 'Undo'
        };

        snackbarContainer.MaterialSnackbar.showSnackbar(data);
    }

I get the folowing error message. How do I get hold of the element with id toast_error

EXCEPTION: TypeError: Cannot read property 'MaterialSnackbar' of null in [null]

PS: I have checked that this.el.nativeElement does give me the correct reference

Edit

Following the answers and comments, I can now get hold of the element by using the same code inside ngAfterViewInit. However, I can't get the snackbar to work. Following is the updated code.

In my component file

   constructor(private el:ElementRef){}


    ngAfterViewInit(){
            var snackbarContainer = this.el.nativeElement.querySelector("#toast_error")
            var data = {
                message: 'Button color changed.',
                timeout: 2000,
                actionText: 'Undo'
            };

            console.log(snackbarContainer.MaterialSnackbar); //prints undefined
            //snackbarContainer.MaterialSnackbar.showSnackbar(data);
        }

The console.log() command prints undefined. I have made sure that the material.min.js is loaded and checked the file, it does include MaterialSnackbar. How should I debug this?

kosta
  • 3,274
  • 7
  • 42
  • 77

3 Answers3

4

I solved the problem by placing the code in ngAfterViewInit() and also calling the upgradeElement as below:

constructor(private el:ElementRef){} 

ngAfterViewInit(){
    window.componentHandler.upgradeAllRegistered();
    var snackbarContainer =         this.el.nativeElement.querySelector("#toast_error")
                    var data = {
                        message: 'Button color changed.',
                        timeout: 2000,
                        actionText: 'Undo'
                    };                           
    snackbarContainer.MaterialSnackbar.showSnackbar(data);
                    }
kosta
  • 3,274
  • 7
  • 42
  • 77
2

If you need direct access to DOM element then have the ElementRef injected:

constructor(ref: ElementRef) ...

And then access the DOM element using:

ref.nativeElement

See here for further information.

Then instead of OnInit, try with AfterViewInit, to make sure the DOM is initialized before running the DOM query -> see here.

Angular University
  • 38,399
  • 15
  • 70
  • 79
0

You can use template variables and @ViewChild to get hold of a specific element:

<div id="toast_error" #toastError> Error message </div>



@ViewChile('toastError') toastErrorDiv;

ngAfterViewInit() {
  toastErrorDiv.doSomething();
}
Günter Zöchbauer
  • 490,478
  • 163
  • 1,733
  • 1,404