35

I have a small problem in integrating a meterial design (http://www.getmdl.io/) in ng2 Can you please help me I will put it in points what I have done

  1. http://www.getmdl.io/started/index.html#tab1, explains the integration of the design
  2. http://www.getmdl.io/components/index.html#textfields-section, this is an example of textfield with floating label and now I Have the Plunkr, which I integrated, but DID NOT WORK can you please have a look As you can see in the index.html I have the css and js files inclustion as suggested by http://www.getmdl.io/started/index.html#tab1

<!-- GetMDL scripts --> <link rel="stylesheet" href="https://storage.googleapis.com/code.getmdl.io/1.0.6/material.indigo-pink.min.css"> <script src="https://storage.googleapis.com/code.getmdl.io/1.0.6/material.min.js"></script> <link rel="stylesheet" href="https://fonts.googleapis.com/icon?family=Material+Icons"> <!-- GetMDL scripts --> And in the app.component.ts file :

import {Component, ViewEncapsulation} from 'angular2/core';

@Component({
    selector: 'my-app',
    template: `<form action="#">
  <div class="mdl-textfield mdl-js-textfield mdl-textfield--floating-label">
    <input class="mdl-textfield__input" type="text" id="sample3">
    <label class="mdl-textfield__label" for="sample3">Text...</label>
  </div>
</form>`,
encapsulation:ViewEncapsulation.None,
})
1
  • 1
    The answers here were really useful, but I found that they were not sufficient when dealing with components that were being rendered by the router. If you run into issues related to the router, you might be interested in this question (and answer). Commented Mar 22, 2016 at 19:43

7 Answers 7

38

Thanks guys, works like a charm, to wrap this up a complete solution, that works well for me (tested with beta6). Without too much boilerplate code. The only thing I did not get to work are really dynamically added elements via *ngFor depending on a component variable. See dynamic elements in the template. Maybe one of you guys knows how to get around that.

See a working plunkr (the preview must be at least 1024px wide to see the header)

Install MDL

npm i material-design-lite --save

Reference it in your index.html

<script src="/node_modules/material-design-lite/material.min.js"></script>
<!-- from http://www.getmdl.io/customize/index.html -->
<link rel="stylesheet" href="/css/customized-material.min.css">

Create MaterialDesignLiteUpgradeElement.ts

import {Directive, AfterViewInit} from 'angular2/core';
declare var componentHandler: any;

@Directive({
    selector: '[mdl]'
})    
export class MDL implements AfterViewInit {
    ngAfterViewInit() {
        componentHandler.upgradeAllRegistered();
    }
}

Then in your component import and register it

import { Component } from '@angular/core';    
import { MDL } from '../../../directives/MaterialDesignLiteUpgradeElement';

@Component ({
  selector: 'my-component',
  directives: [ MDL ],
  templateUrl: 'app/components/Header/Header.html'
})
export class Header {
  public dynamicArray:number[] = [];

  add() {
    this.dynamicArray.push(Math.round(Math.random() * 10));
  }
}

And in your template add mdl to the root component

<header mdl class="mdl-layout__header">
    <div class="mdl-layout__header-row">
      <span class="mdl-layout-title">Home</span>
      <div class="mdl-layout-spacer"></div>

      <button class="mdl-button mdl-js-button mdl-js-ripple-effect mdl-button--icon"
              (click)="add()">
          <i class="material-icons">add</i>
      </button>
      <button class="mdl-button mdl-js-button mdl-js-ripple-effect mdl-button--icon" id="hdrbtn">
          <i class="material-icons">more_vert</i>
      </button>
      <ul class="mdl-menu mdl-js-menu mdl-js-ripple-effect mdl-menu--bottom-right" for="hdrbtn">
          <li class="mdl-menu__item">Static entry</li>

          <!-- semi dynamic, known when view is created -->
          <li class="mdl-menu__item" *ngFor="#nr of [1,2,3]">Semi Dynamic entry {{nr}}</li>

          <!-- dynamic, depends on service manipulated array -->
          <li class="mdl-menu__item" *ngFor="#nr of dynamicArray">Dynamic entry {{nr}}</li>
      </ul>
  </div>
</header>
Sign up to request clarification or add additional context in comments.

9 Comments

Thanks Rob, this was very helpful. You noted that you couldn't add dynamic elements. Is that not what you were doing with the menu items? Perhaps you can explain further.
Hi Steve, basically anything that gets generated at runtime. The semi dynamic stuff can be generated before OnInit fires, because [1,2,3] is known and therefore the according views can be rendered. Content of dynamicArray isn't. We switched to ng2-material, works better for us.
A better solution is to use AfterViewChecked interface to be able to do it only once, on the root application component. See my full answer here : stackoverflow.com/a/39040342/1969987
I am getting directive does not exist in type component... Anyone else encountering this? Do I need to be using both the beta version ('angular2/core') and a release version('@angular/core') for this to work?
For dynamically added elements after the initial view is loaded, you can try using ngAfterContentChecked() instead of AfterViewChecked.
|
9

The problem is Material Design Lite isn't designed to be used with dynamic pages like those generated by Angular2. That said it should be possible by using the MDL componentHandler.upgradeElement function.

More information on this can be found here: http://www.getmdl.io/started/#dynamic

I'd suggest getting an ElementRef in your Angular components then calling this function on the element ref in one of your components lifecycle hooks, probably ngAfterViewInit()

Comments

8

I am able to get the solution from angualrjs channel, and it is super cool solution, ofource we have to use componentHandler.upgradeElement(this.elementRef.nativeElement);

//This is the way to make the

@Directive({
  selector: '[mdlUpgrade]'
})
class MdlUpgradeDirective {
  @Input() mglUpgrade;

  constructor(el: ElementRef) {
    componentHandler.upgradeElement(el.nativeElement);
  }
}

@Component ({
  selector: 'login',
   ...
  directives: [MdlUpgradeDirective]
})

and use the Directive on the HTML tags to use it.

It works,

NOTE: https://github.com/justindujardin/ng2-material , this guys has made super cool material stuff, can refer this too

5 Comments

a u actually using MDL + ng2-material together? Did you had any issues with MDL components (angular2 creating parent tag/selector for each component which is braking its view)?
I found that this works better when calling componentHandler.upgradeElement(el.nativeElement); in ngAfterViewInit() (otherwise upgrade is done before other directives, like ngModel, kick into action)
I'm not questioning the solution you provided only clarifying something about the link you provided. The article mentioned above is referencing Material2, not Material Design Lite, which is different.
@Helzgate, If you have read the whole line, you would have got an idea, It is basically a reference for other design.
I have to say, I'm very confused, why the plain adding classes on html elements solution needs to be so complicated?
1

I was facing the same problem (as I'm using the same template as you).

Just try componentHandler.upgradeAllRegistered() it will work fine in your case.

A different issue occurs when you try to break the header into small components.

Comments

0

Just thought it's worth mentioning here that the official Material Design for Angular 2 library is now in alpha.2, so you might consider starting new projects with it.

4 Comments

I looked at this and I don't fully understand how to use it in a project. Would love to see an example if anyone has one!
Take a look at the demo-app in the source github.com/angular/material2/tree/master/src/demo-app
Or if you like, I can copy a snippet from my project later today
A year later, they still don't have basic components like tables implemented. This really isn't production ready, don't make the same mistake I did.
0

just import ElementRef and OnInit from the angular2/core and inject it to a constructor as so:

constructor(@Inject(ElementRef) elementRef: ElementRef) {
    this.elementRef = elementRef;

}

then use an ngOnInit method and use the componentHandler.upgradeElement on any dynamically added tag you used.

Comments

0

The ng2-webpack Demo project includes a simple ng2 CRUD application that uses vanilla MDL

Steps:

  • npm install --save material-design-lite
  • import the entire library in src/vendor.js
  • or just the desired components
  • in src/style/app.scss, import the desired components:

Issues:

Issue - MDL augmented DOM effects are not applied:

  • consistently during state changes
  • during route changes

Solution:

ngAfterViewInit() {
    // Ensure material-design-lite effects are applied
    componentHandler.upgradeDom();
}

see Working with Material Design Lite for more details.

Comments

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.