deanT
deanT

Reputation: 125

Ember JS: How to import Material Components Web JS

I'm trying to use Material Components Web(MDC-Web) with an EmberJS application. I've installed material-components-web with Yarn.

yarn add material-components-web --dev

This installed [email protected].

I have the sass/CSS working but can't figure out how to include/import the JS. Could someone show me how it would import that into my component js file and/or my component template file.

I get an no file error when I do an

app.import('node_modules/material-components-web/dist/material-components-web.js')

Thanks for any help!

Upvotes: 0

Views: 471

Answers (1)

Don Omondi
Don Omondi

Reputation: 946

This is how I normally use Material Components Web in my Ember project. Has worked for me since Ember version 2.x upto the latest 3.x.

First in ember-cli-build.js. Import the required js file

  app.import('node_modules/material-components-web/dist/material-components-web.js', {
    using: [{
      transformation: 'fastbootShim'
    }]
  });

The using part is only applicable if you use Fastboot (which you should) so as to exclude the file from executing in a Fastboot environment.

Then fear not, in an Ember component on the didInsertElement hook, activate the MDC component for example for a modal drawer component I have used code like this.

  tagName: 'aside',
  classNames: ['mdc-drawer', 'mdc-drawer--modal', 'app-drawer'],

  didInsertElement: function () {
    let component = this;

    let componentJqueryObject = component.$();
    let componentElement = componentJqueryObject[0];

    let MDCDrawer = mdc.drawer.MDCDrawer;
    let drawer = new MDCDrawer(componentElement);

    $('header').on('click', '.drawer-menu', function() {
      drawer.open = !drawer.open;
    });

    $('body').on('click', 'main', function() {
      drawer.open = false;
    });

    $('aside').on('click', 'a', function() {
      drawer.open = false;
    });
..........

For a MDC top-app-bar component (latest MDC only) I've used this

  tagName: 'header',
  classNames: ['mdc-top-app-bar', 'mdc-top-app-bar--fixed'],

  didInsertElement: function () {
    let component = this;

    let componentJqueryObject = component.$();
    let componentElement = componentJqueryObject[0];

    let topAppBar = new mdc.topAppBar.MDCTopAppBar(componentElement);
    let mainEl = document.getElementById('app-main');
    topAppBar.setScrollTarget(mainEl);

............

Note: Its important to always use the didInsertHook for 2 reasons. 1.) According to Ember Docs, didInsert is at that point where the component's HTML is guaranteed to be inserted in the DOM. 2.) According to Fastboot Docs, didInsert is not executed in FastBoot mode which runs in Node yet MDC is a browser thing.

Enjoy!

EDIT: Based on Question below

import Component from '@ember/component';
import { get } from '@ember/object';
import $ from 'jquery';

export default Component.extend({
  tagName: 'aside',
  classNames: ['mdc-drawer', 'mdc-drawer--modal', 'app-drawer'],

  didInsertElement: function () {
    let component = this;

    let componentJqueryObject = component.$();
    let componentElement = componentJqueryObject[0];

    let MDCDrawer = mdc.drawer.MDCDrawer;
    let drawer = new MDCDrawer(componentElement);

    $('header').on('click', '.drawer-menu', function() {
      drawer.open = !drawer.open;
    });

    $('body').on('click', 'main', function() {
      drawer.open = false;
    });

    $('aside').on('click', 'a', function() {
      drawer.open = false;
    });

    // mdc web used to override the a href link element in the drawer component, causing all links to open with a page reload, use this hack if your version still does, assign every a href link a custom-link class and add data attributes to keep things the Ember way

    let router = get(component, "router");

    component.$().on("click" , ".custom-link" , function(e) {
      e.preventDefault();

      drawer.open = false;

      let routeName = $(this).data("route");
      let modelId = $(this).data("id");

      if(modelId){
        router.transitionTo(routeName , modelId);
      } else {
        router.transitionTo(routeName);
      }
    });

  }
});

Upvotes: 1

Related Questions