6

I am learning Angular2 but I have problem about using Angular2 with MDL. Why MDL navigation bar is not working with Angular2? When I use Navigation bar with header and drawer, drawer is not working so I cannot click on it, I cannot see drawer's icon. There is another problem: textfields also is not working correctly. I want to use mdl-textfield--expandable (Search) but when I click on this search field it is not expanding. However, without Angular2 it is working fine.

UPDATE

it is my app.html file

<div class="demo-layout-waterfall mdl-layout mdl-js-layout">
    <header class="mdl-layout__header mdl-layout__header--waterfall">
        <!-- Top row, always visible -->
        <div class="mdl-layout__header-row">
            <!-- Title -->
            <span class="mdl-layout-title">Title</span>
            <div class="mdl-layout-spacer"></div>



            <div class="mdl-textfield mdl-js-textfield mdl-textfield--expandable
                  mdl-textfield--floating-label mdl-textfield--align-right">
                <label class="mdl-button mdl-js-button mdl-button--icon" for="waterfall-exp">
                    <i class="material-icons">search</i>
                </label>
                <div class="mdl-textfield__expandable-holder">
                    <input class="mdl-textfield__input" type="text" name="sample" id="waterfall-exp">
                </div>
            </div>


        </div>
        <!-- Bottom row, not visible on scroll -->
        <div class="mdl-layout__header-row">
            <div class="mdl-layout-spacer"></div>
            <!-- Navigation -->
            <nav class="mdl-navigation">
                <a class="mdl-navigation__link" href="">Link</a>
                <a class="mdl-navigation__link" href="">Link</a>
                <a class="mdl-navigation__link" href="">Link</a>
                <a class="mdl-navigation__link" href="">Link</a>
            </nav>
        </div>
    </header>

    <div class="mdl-layout__drawer">
        <span class="mdl-layout-title">Title</span>
        <nav class="mdl-navigation">
            <a class="mdl-navigation__link" href="">Link</a>
            <a class="mdl-navigation__link" href="">Link</a>
            <a class="mdl-navigation__link" href="">Link</a>
            <a class="mdl-navigation__link" href="">Link</a>
        </nav>
    </div>

    <main class="mdl-layout__content">
        <div class="page-content">
            <!-- Your content goes here -->
            
           

        </div>
    </main>
</div>

app.ts

import { Component } from 'angular2/core';


@Component({
    selector: 'my-app',
    templateUrl: 'app/app.html',
    styleUrls: ['app/assets/css/material.min.css']

})
export class AppComponent { }

main.ts

import {bootstrap}    from 'angular2/platform/browser'
import {AppComponent} from './app.component'

bootstrap(AppComponent);
6
  • 1
    Welcome to StackOverflow. Please check the help menu about how to ask good questions. Please add the code that demonstrates what you tried. Explain what the actual and the expected behavior is. "doesn't work" doesn't contain any useful information. Commented Jun 17, 2016 at 7:51
  • I have explained what is not working. It just shows nothing about drawer! Code is known by everyone because it is in (MDL website) Commented Jun 17, 2016 at 7:56
  • 1
    Please read again my comment above and respond to each sentence. Otherwise your chances of getting any useful response are ~0. Commented Jun 17, 2016 at 8:00
  • @GünterZöchbauerm I have added, will you answer? Commented Jun 17, 2016 at 8:48
  • I think the answer below is a good guess. Commented Jun 17, 2016 at 8:49

2 Answers 2

14

As explained by @talkdirty :

the MDL component handler (the js part of mdl you include which handles animations and layout things) doesn't know anything about the mdl components you include in that template, since it is included dynamically by Angular2 sometime after the MDL component handler looks for MDL components to handle.

His solution works well for a single component :

declare var componentHandler: any;
export class MyComponent {
    ngAfterViewInit(){
        componentHandler.upgradeAllRegistered();
    }
}

But when using Angular2 routing, you will need to add this code on every route component, which is not really smart and convenient

As a solution, you can use AfterViewChecked interface instead of 'AfterViewInit'

Full Solution :
Write an 'mdl' directive that you will use on the root HTML tag of you app component.

import {Directive, AfterViewChecked} from '@angular/core';
declare var componentHandler: any;

@Directive({
    selector: '[mdl]'
})
export class MDLUpgradeElementDirective implements AfterViewChecked {
    ngAfterViewChecked() {
        componentHandler.upgradeAllRegistered();
    }
}

Then declare your root component as following:

import { Component } from '@angular/core';
import { ROUTER_DIRECTIVES } from '@angular/router';
import { MDLUpgradeElementDirective } from './mdl-upgrade-element.directive';

@Component({
  moduleId: module.id,
  selector: 'app-root',
  template: '
  <div mdl class="mdl-layout mdl-js-layout mdl-layout--fixed-header">
    <header class="mdl-layout__header">
      <div class="mdl-layout__header-row">
        <!-- Title -->
        <span class="mdl-layout-title">{{title}}</span>
      </div>
    </header>
    <main class="mdl-layout__content">
      <!-- Router Outlet -->
      <router-outlet></router-outlet>
    </main>
  </div>
  '
  directives: [
    ROUTER_DIRECTIVES,
    MDLUpgradeElementDirective
  ]
})
export class AppComponent {
  title = 'MDL Application';
}

Then you don't need to worry anymore on the mdl js handlers on every components and routes.

Sign up to request clarification or add additional context in comments.

2 Comments

Works on Angular 2 RTM with 1.3.0 of material js. Make sure you do not use "defer" in your script tag or componentHandler will be undefined.
@Julien Boulay your solution does not work any more i get error same as post. Update solution it will be helpful
4

Since you aren't posting any code examples, I'm guessing you're in this scenario (this is the usual pitfall when using MDL with Angular2): you include MDL in your Angular 2 @Component template.

@Component({
    template: `mdl things here`,
    ....
}) export class YourComponent {}

If that's the case, the MDL component handler (the js part of mdl you include which handles animations and layout things) doesn't know anything about the mdl components you include in that template, since it is included dynamically by Angular2 sometime after the MDL component handler looks for MDL components to handle.

Long story short, tell MDL to recheck the DOM for new components to handle after your component initializes:

declare var componentHandler: any;
export class MyComponent {
    ngAfterViewInit(){
        componentHandler.upgradeAllRegistered();
    }
}

3 Comments

I have added componentHandler. However, it does not solved my problem
ngAfterViewInit() only fires once, which means that template changes that happen afterwards aren't captured. ngAfterContentChecked(), if used instead, will work on app load and will upgrade any components added after the fact.
I know this is old, but how does angular know what componentHandler is in this context?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.