How does import statements work in ember-cli? - ember.js

Am quite new to emberjs and ember-cli.
And I have always been wondering how a statement like this works:
import Ember from 'ember'
Does 'ember build' look up for 'ember' in node_modules?
I understand statements like this with relative paths:
import ENV from './config/environment'
but not the ones referred without a path.
This question raises in connection with Could not find module ember-validations, in an effort to find its root cause.

The sort answer is that Ember-CLI registers the global objects directly with the module system. Take a look at the code here. While it's wrapped in a little helper code, they essentially do this:
define('ember', [], function() {
return {
'default': window.Ember,
};
});
Then, Ember-CLI converts your import statement during compilation:
import Ember from 'ember';
Gets converted to:
var Ember = require('ember')['default'];
Keep in mind that this is how it's done when using a transpiler to use AMD modules. I'm not 100% sure how that code would work if we were using a native ES6 implementation, although I know that the syntax supports this kind of thing.

Related

import node js module in ember js framework

I am trying to import a simple node js module into Ember js. I followed the quick start at https://guides.emberjs.com/v3.8.0/getting-started/quick-start/ and got the People List working.
Then I added the simple upper-case module using npm install upper-case and added app.import('node_modules/upper-case/upper-case.js'); to ember-cli-build.js as mentioned in https://guides.emberjs.com/release/addons-and-dependencies/managing-dependencies/.
After that, I opened scientists.js and added import to upper-case as follows:
import Route from '#ember/routing/route';
//import uc from 'upper-case';
export default Route.extend({
model() {
var arr = new Array();
arr[0] = 'Marie Curie'; // uc('Marie Curie');
arr[1] = 'Mae Jemison';
arr[2] = 'Albert Hofmann';
return arr;
}
});
If I remove the comments, it shows me a blank screen. If I use 'Marie Curie'.toUpperCase() it works, but I want to be able to import such node modules. How can I achieve this?
I have already tried exception while importing module in ember js and ember-auto-import, but they don't seem to work for me. The above method I tried seems to be simple and would be nice if it can work this way.
PS: I could make upper-case work in other JS frameworks such as React and Vue, so the module itself doesn't have any issues.
if you install ember-auto-import, you'll be able to use any npm package like how the particular npm package's documentation says to use it (provided the particular npm package is configured correctly on build).
https://github.com/ef4/ember-auto-import
This'll be a default soon (and is recommended over using app.import)
The reason ember-auto-import is recommended over app.import is because there are ~ 5 different module formats JS can exist in, and you need to worry about those when using app.import. ember-auto-import, powered by webpack, abstracts all that away from you.
fwiw, JS has .toUpperCase() built in: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/toUpperCase
so you don't need that particular module.
Edit
I have already tried exception while importing module in ember js and ember-auto-import, but they don't seem to work for me. The above method I tried seems to be simple and would be nice if it can work this way.
did you get any errors with this?

Ember error:Ember is not defined no-undef

Hi I am following through with Plural sight course "Getting started with Ember 2"; I am stuck with this error: 'Ember' is not defined no-undef;
my code looks like this ember dot dollar sign dot get json two brackets; this is inside route ; the code works fine with static data. I am sorry the editor would not allow me to paste my code
Update:
Right way and best practice is to import Ember like this import Ember from "ember";
This is just lint error. you can add an exception for Ember. In .eslintrc.js file you can add
"globals": { "Ember": true }
Or if you dont want this rule be enabled then you can turn it off
rules: {
"no-unused-vars": "off"
}

How to import 'ember-routing/system/query_params' in an ember-cli app

I think I do not understand well the modules hierarchy in an ember-cli app.
I need to
import QueryParams from 'ember-routing/system/query_params';
in one of my app services.
but the console shouts at me
Error: Could not find module 'ember-routing/system/query_params' imported from 'my-app/services/menu'
What path should I use to import this module ?
Thanks
I wanted to do the same thing; get the QueryParams class so I could create a higher-level link-to that accepted a query param key.
Luckily QueryParams is a really basic class: you can create your own (compatible for use in {{link-to}} version of it:
import Ember from 'ember';
const { Object } = Ember;
export default Object.extend({
isQueryParams: true,
values: null,
});
Taken from QueryParams source
I'm guessing that you got that path from the Ember source. Unfortunately, Ember's internal package structure is not exposed externally to other module loaders such as Ember-CLI's. As of now, the only way to access the Ember library and its internals is to import the main object from ember and use that.
// This...
import Ember from 'ember';
const Controller = Ember.Controller;
// Not this...
import Controller from 'ember-runtime/controllers/controller';
Unfortunately for you the QueryParams object is not exposed in this manner. However, that object is simply an implementation detail and I can't see a reason why you would need it in your app. I'm guessing you might be mistaken as to what that actually does. The guide on query parameters might help you there.
It is possible to import from ember internals. But it is considered as hack.
const metal = Ember.__loader.require('ember-metal');
Above is how to import from ember-metal to import ember-routing/system/query_params review loader registry for proper import
const registry = Ember.__loader.registry
console.log(registry);

How to import non amd library ember-cli

I am using Ember-CLI and now I faced the problem of importing AmplifyJS in my project. I downloaded Amplify using Bower however the library is not in an ES6 format. Therefore, when I try to use it in my project, I simply can't import it.
Basically I would want to do:
import Amplify from amplify;
//use amplify here
Brocfile.js
app.import('bower_components/amplify/lib/amplify.js');
Since a lot of libraries are no in the ES6 format yet, my question is: "Is there a way to easily import or use ES5 librairies in ES6".
If not, what is the recommended way of doing that in Ember?
You can't import Amplify from amplify; because it's not a module.
You've almost got it but just don't try to import the library. You need to reference it as a global the way that you would outside of an ember-cli app.
From the docs:
Provide the asset path as the first and only argument:
app.import('bower_components/moment/moment.js');
From here you would use the package as specified by it’s documentation, usually a global variable. In this case it would be:
import Ember from 'ember';
/* global moment */
// No import for moment, it's a global called `moment`
// ...
var day = moment('Dec 25, 1995');
Note: Don’t forget to make JSHint happy by adding a /* global MY_GLOBAL */ to your module, or by defining it within the predefs section of your .jshintrc file.
-- http://www.ember-cli.com/#standard-non-amd-asset
If you look at line 15 of the code https://github.com/mikehostetler/amplify/blob/master/lib/amplify.js#L15, library is attaching itself to global which is passed in here https://github.com/mikehostetler/amplify/blob/master/lib/amplify.js#L124
So basically you can directly use the global version of library anywhere like amplify.subscribe(...)

Addon not working

I have an Ember Addon which I've put up at Github here:
https://github.com/lifegadget/ember-dictionary
It passes all its unit tests and in a non addon form it is working fine in one of my projects but I'd like to lift it out the project and be able to use it as an addon. Still I'm clearly missing a step in how to expose the two Ember classes. This can be seen in the dummy app which tries to create a very simple model like so:
import DS from 'ember-data';
import DictionaryModel from 'ember-dictionary';
export default DictionaryModel.extend({
foo: DS.attr('string')
});
Then when the route (tests/dummy/routes/index.js) tries to use the model I get the following error:
Error while processing route: index Cannot read property 'extend' of undefined TypeError: Cannot read property 'extend' of undefined
To me this feels like a ES6/namespacing issue but I'm not sure how to overcome it. I did try the following more explicit import statement:
import DictionaryModel from 'ember-dictionary/models/dictionary-model';
but the same error occurred. Any help would be greatly appreciated.
I have bumped into enough walls that I think I can at least partially answer my question but some questions still remain so I won't mark this answer correct with the hope that others may post a more complete answer.
The first distinction I realised I hadn't been making clear enough for myself was whether to target the Ember App's namespace or to target an independent namespace for the addon. Classes defined in the app directory of the addon will be available to any application which uses the Addon in it's own namespace. In contrast, classes in the addon directory will be namespaced to the addon's namespace.
I have seen a lot people define classes in the addon's app directory and then proxy it through to the addon directory with something like:
// addon/mixins/dictionary.js
import DictionaryMixin from 'ember-dictionary/mixins/dictionary';
export default DictionaryMixin;
Although I've seen this I am still having problems getting these external namespaced classes to work. I think there may be another step needed to add a index.js entry point for the addon and then export these classes there. In any event, I'll leave this area alone as I decided to get the internal namespaced solution working first.
My next problem in the internal namespaced solution was centered around the dummy application that gets built as part of the addon creation process. I wanted this dummy application to have a model which would use the Mixin I created in the addon and I thought I'd be able to refer to it as:
import DictionaryMixin from 'ember-dictionary/mixins/dictionary';
but this couldn't be resolved by the Dummy test application so I had to resort to:
import DictionaryMixin from '../mixins/dictionary';
Which I guess is appropriate considering that my "external namespaced solution" isn't working yet ... falling back to the internally namespaced solution was required.