Best way of passing arguments to ember addon source code - ember.js

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
}
}
};
};

Related

EmberJS expose env variable as route

I would like to configure a URL differently in my ember app depending if the app is running in production or development mode. Is this possible to do by loading the endpoints into config/environment.js and accessing the value of the ENV object in a handlebars template? Maybe I have to expose the ENV value in a controller? Or is there some other mechanism for doing this?
Something like this:
// config/environment.js
if (environment === 'development') {
ENV.zzz.url = "http://www.reddit.com";
}
if (environment === 'production') {
ENV.zzz.url = "http://www.google.com";
}
// app/controllers/application.js
export default Ember.Controller.extend({
siteUrl: ENV.zzz.url
...
// somefile.hbs
Funspot
yes. you can do import config from 'app-name/config/environment';
and access it like config.zzz.url

How to load external JS file in component using ember-cli

I have created an ember app with a component, and I am trying to figure out how I can load a external JS file that is stored in the vendor dir of the app within the component. The code for the component looks like the following,
// app/components/bubbles-page.js
import Ember from 'ember';
export default Ember.Component.extend({
didInsertElement: function() {
// this.$() is a scoped selector to the current view
// bubbles();
// window.onload = bubbles();
// the below line gives the following error,
this.$().bubbles();
// ERROR
//TypeError: this.$(...).bubbles is not a function
// END ERROR
}
});
And the ember-cli-build.js looks like the following,
/* global require, module */
var EmberApp = require('ember-cli/lib/broccoli/ember-app');
module.exports = function(defaults) {
var app = new EmberApp(defaults, {
// Add options here
//
});
// Use `app.import` to add additional libraries to the generated
// output files.
//
// If you need to use different assets in different
// environments, specify an object as the first parameter. That
// object's keys should be the environment name and the values
// should be the asset to use in that environment.
//
// If the library that you are including contains AMD or ES6
// modules that you would like to import into your application
// please specify an object with the list of modules as keys
// along with the exports of each module as its value.
app.import( app.bowerDirectory + '/d3/d3.min.js');
app.import('vendor/bubbles.js');
return app.toTree();
};
Your ember-cli-build.js seems ok.
As for your component file, you can use Ember.run.scheduleOnce('afterRender', callback) to wait for the DOM to render and then call your jQuery plugin.
Also, normally with jQuery plugins, you would have to pass a jQuery selector with which to call the function.
Try the following:
// app/components/bubbles-page.js
import Ember from 'ember';
export default Ember.Component.extend({
didRender() {
this.$('.my-bubbles-container').bubbles();
}
});
Replace .my-bubbles-container with your jQuery selector. I am not familiar with the jQuery plugin you're trying to use but normally that's how jQuery plugins would be used.
You can read more about how to initialize a jQuery component on [this blog post][1].
Updated answer
After learning that your bubbles.js file wasn't a jQuery plugin and that it was a function that operates on the global window, you can call it like this:
// app/components/bubbles-page.js
import Ember from 'ember';
export default Ember.Component.extend({
didRender() {
bubbles();
}
});
If your function is a global function, you will need to add /* global bubbles */ to your component file, or add bubbles to the predef array in the .jshintrc file to avoid the JSHint errors.
This might be a silly question but did you restart your ember serve after adding the import to ember-cli-build? Changes to the Brocfile or ember-cli-build won’t be picked up until you restart.
Another thing you could try is to add { type: 'vendor'} to your import statement: app.import('vendor/bubbles.js', {type: 'vendor'});

How to access environment variables in .profile for a controller?

I have a problem accessing the environment variables in my EmberJs app.
I want to use the environment variable set in the .profile file of the server.
My .profile in the server
export SERVER_NODE=testNode
I already tried this solution :
process.env like node.js in my config/environment.js but it doesn't
work, i cannot access it in my app (Stack Post here)
So if you have any idea about how I can do this, I take it.
Thanks you.
Try using the ember-cli-dotenv Ember addon: https://github.com/fivetanley/ember-cli-dotenv
This will let you access variables from a .env file in config/environment.js. You can then access these variables from a component or service by importing config/environment.js.
Example:
.env
CLIENT_KEY=THEKEY
CLIENT_SECRET=SECRETSECRET
config/environment.js
module.exports = function(environment) {
var ENV = {
API: {
clientKey: process.env.CLIENT_KEY,
clientSecret: process.env.CLIENT_SECRET
}
}
};
app/services/example.js
import Ember from 'ember';
import ENV from '../config/environment';
export default Ember.Service.extend({
clientKey: ENV.API.clientKey, // 'THEKEY'
clientSecret: ENV.API.clientSecret // 'SECRETSECRET'
});

How to read Ember-cli config file from addon?

Is there another way besides reading config file with
this.container.lookupFactory('config:environment').modulePrefix;
inside and object initializer? Seems a bit odd to do this
With ember 2.4.x (the LTS version which I recommend using), you can do the following:
import Ember from 'ember';
import layout from './template';
export default Ember.Component.extend({
layout,
magicKey: Ember.computed.reads('config.magic.key'),
});
This assumes that you have set the config/environment.js file as follows:
module.exports = function(environment) {
var ENV = {
/* .... */
APP: {
// Here you can pass flags/options to your application instance
// when it is created
},
magic: {
key: "something awesome"
},
};
return ENV;
};
EDIT: Adding how to get the config object below, to answer the question from #jcbvm.
For this to work, you will need to export the config in your app directory in your addon as follows: (in your addon_name/app/component/component_name/component.js )
import config from '../../config/environment';
export default component.extend({ config });

How to do dependency injection in Ember with Ember CLI?

First, I made a small Ember app without Ember CLI.
I had this piece of code.
window.MyApp = Ember.Application.create({
ready: function() {
this.register('session:current', MyApp.SessionController, { singleton: true });
this.inject('controller', 'session', 'session:current');
}
});
This worked.
Then I decided to rewrite everything from scratch with Ember CLI.
I edited the file app/app.js and added the ready hook just like in my previous version.
var App = Ember.Application.extend({
modulePrefix: config.modulePrefix,
podModulePrefix: config.podModulePrefix,
Resolver: Resolver,
ready: function() {
this.register('session:current', App.SessionController, { singleton: true });
this.inject('controller', 'session', 'session:current');
}
});
This doesn't work.
The session controller does exist. That's the content of the file app/controllers/session.js
export default Ember.Controller.extend({
isLoggedIn: false,
});
The error message I get is
TypeError: Attempting to register an unknown factory: `session:current`
It appears in the browser.
I googled that message, but I found nothing about dependency injection in Ember CLI.
Any idea?
In ember-cli you can use ember generate service <name of service> and ember generate initializer <name of initializer> to build the stubs to achieve this, which is far better than fiddling about with app.js.
You create a service basically like this:
// app/services/notifications.js
import Ember from 'ember';
export default Ember.Object.extend({
initNotifications: function() {
// setup comes here
}.on('init'),
// Implementation snipped, not relevant to the answer.
});
And the initializer, which injects the service into the component(s) of your application which need it:
// app/initializers/notifications-service.js
import Notifications from '../services/notifications';
export default {
name: 'notification-service',
after: 'auth-service',
initialize: function( container, app ) {
app.register( 'notifications:main', Notifications, { singleton: true } );
app.inject( 'component:system-notifications', 'notificationService', 'service:notifications' );
app.inject( 'service:auth', 'notificationService', 'service:notifications' );
}
};
With that, it becomes available as notificationService on the components specified.
Documentation on the subject of dependency injection in Ember can be found at http://emberjs.com/guides/understanding-ember/dependency-injection-and-service-lookup/