Use EmberScript in Ember-CLI app - ember.js

How does one use emberscript in an Ember-cli app? I've installed the broccoli-ember-script node module but I can't figure out how to incorporate it into the default Ember-cli configuration of Brocfile.js.

This is how I ended up doing it:
var EmberApp = require('ember-cli/lib/broccoli/ember-app');
var filterEmberScript = require('broccoli-ember-script');
var app = new EmberApp();
var tree = app.toTree();
tree = filterEmberScript(tree);
module.exports = tree;
Also, apparently ember-script will include Ember automatically so importing it will cause an error. There's an open issue about this.

Related

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 material-components-web#0.41.0.
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!
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);
}
});
}
});

Acces environment.js from Ember addon index.js

I am building a Ember addon and I will like to know if there is a way to access the config/environment.js file from the root index.js. Basically I would like have the same config value used from the root index.js and a component.
Thanks
const config = this.project.config()
You can simply require it:
// index.js
var environment = 'production'; // optional
var ENV = require('config/environment')(environment);
console.log(ENV.baseURL);

Using moment.js with Ember, Ember-CLI

I have been trying to get the moment.js library to work with an Ember application using the Ember-cli. Note I am fairly new to ES2015.
Ember 2.2.0
Ember-cli 1.13.13
my ember-cli-build
/*jshint node:true*/
/* global require, module */
var EmberApp = require('ember-cli/lib/broccoli/ember-app');
module.exports = function(defaults) {
var app = new EmberApp(defaults, {
//options
});
app.import('bower_components/moment/moment.js');
return app.toTree();
};
and my .jshintrc
"predef": [
"document",
"window",
"-Promise",
"moment"
],
and my controller
/* global moment:true */
import Ember from 'ember';
export default Ember.Controller.extend({
firstName: null,
lastName: null,
day: function () {
return moment('Dec 25, 1995');
}.property()
});
I always get an error that 'moment' has not been defined. I read that the latest moment.js has stopped producing a global 'moment' but I'm not sure what to do about it.
The builds work. If I pull up the generated vendor.js I can see the complete contents of the moment.js file in it. However when I look at vendor.js in the chrome debugger the contents are omitted. I wasn't sure if this was due to some optimization.
the best way to install moment.js in ember app is to use ember moment addon
after installing it you will be able to use it as
import moment from 'moment';
plus you will get various helpers

Best way of passing arguments to ember addon source code

TL;DR
Is it possible to pass the options from the addon's index.js file to the addon's Ember application?
More detail
Ember CLI addon's allow you to pass options to an addon by setting options in your Brocfile.js.
var EmberApp = require('ember-cli/lib/broccoli/ember-app');
var app = new EmberApp({
myAddon: {
enabled: false // TODO - Change when CLoudfront is implemented
},
});
You can then access these options in the addon's index.js file like so:
module.exports = {
name: 'my-addon',
included: function(app) {
var options = app.options.myAddon;
}
}
However, what if I want to use these options in an Ember component or view or other class in the addon? For example, a component:
import Em from 'ember';
export default Em.Component.extend({
doSomething: function() {
if (this.get('options.enabled')) {
// Then do something
}
},
});
Is it possible to pass the options from the addon's index.js file to the addon's Ember application?
Please note, I'm aware you could just pass the argument to the component in the template but that's not the point of this question. Thanks.
I think what you're trying to accomplish is best implemented using config/environment.
You can either add your options to your addons config/environment.js file. This object will be merged with you applications config/environment.js.
module.exports = function(/* environment, appConfig */) {
return {
myaddon {
enabled: true
}
};
};
Or if you are feeling funky, you can override the default behaviour of the addons config hook in index.js to manually add the options. But the happy path should be considered adding it to config/environment.js
In your component you can then import the config with:
import config from '../config/environment';
If you also need the options to be added to your app instance. You can add the options under the APP property in config/environment.js. The content of the APP property are added to the app instance. In your addon's config/environment.js put:
module.exports = function(/* environment, appConfig */) {
return {
APP: {
// Here you can pass flags/options to your application instance
// when it is created
myaddon {
enabled: true
}
}
};
};

Ember-Rails and namespaced templates

I have a Rails app that is namespaced into three sections (almost 3 apps that share models). I would like for each namespaced section to have it's own Ember app. These apps are never loaded in the same layout so don't have to know anything about each other. In fact I would like to keep the code as separate as possible for when the app can eventually be really split up.
I am trying to do this using the ember-rails gem.
Basically it is like this question:
How can I specify an alternative directory for my HandlebarsJS templates with the ember-rails gem?
And the answer there works, but I'm pretty sure using templates_root limits me to just one namespace. So I couldn't also have an admin.js and admin/templates namespace as well as a customer.js and customer/templates namespace.
So does anyone know if ember-rails will support multiple namespaced Ember apps and render multiple template roots as a result?
Thanks!
As posted here you can have namespace templates by adding a custom resolver to each app.
App1 = Ember.Application.create({
Resolver: Ember.DefaultResolver.extend({
resolveTemplate: function(parsedName) {
parsedName.fullNameWithoutType = "app1/" + parsedName.fullNameWithoutType;
return this._super(parsedName);
}
})
});
App2 = Ember.Application.create({
Resolver: Ember.DefaultResolver.extend({
resolveTemplate: function(parsedName) {
parsedName.fullNameWithoutType = "app2/" + parsedName.fullNameWithoutType;
return this._super(parsedName);
}
})
});
App3 = Ember.Application.create({
Resolver: Ember.DefaultResolver.extend({
resolveTemplate: function(parsedName) {
parsedName.fullNameWithoutType = "app3/" + parsedName.fullNameWithoutType;
return this._super(parsedName);
}
})
});