Ember.JS: Ember-Objects and where they are exported to - javascript

I am trying to grasp the underlying system of Ember.JS. Whereto are those Ember-Objects exported and how are they used?
components:
export default Ember.Component.extend({ ... });
controllers:
export default Ember.Controller.extend({ ... });
models:
export default DS.Model.extend({ ... });
routes:
export default Ember.Route.extend({ ... });
... they all follow the same structure: they extend some object and export something.
Somebody knows more? Thanks!

I think you are interpreting the export keyword wrong here.
It doesn't mean files are written somewhere else in a different format, but:
if a module (= file) is imported, then things in that file that are exported are available to the importer.
Think of it as making some parts available to other modules, a public API in shorter terms.
Ember files usually only export one thing as there is a strong naming convention making the Ember engine work that way.
This is why if you declare a /user route, it will try to use your routes/user.js, controllers/user.js, and templates/user.hbs files if they exist, without you having to specify anything.
In a similar way, this is what makes a component usable inside a template.
Hence the one-liner export default Ember.Something.extend({ ... }); you find in these files.
However, you can have modules (= files) with multiple export statements in a single file, this is perfectly valid.
// Example from babel website
// lib/mathplusplus.js
export * from "lib/math";
export var e = 2.71828182846;
export default function(x) {
return Math.exp(x);
}
// app.js
import exp, {pi, e} from "lib/mathplusplus";
console.log("e^π = " + exp(pi));
The Learn ES2015 from Babel website has a few examples, and you can read more about the export statement on MDN.
In Ember applications, you will - from my experience - find files with multiple exports mostly in some directories meant to be used by more than one module in the application, or not bound to the Ember engine auto-import, like some utils.
The following example shows an Ember.Controller importing a variable exported from another module:
// utils/messages.js
export var hello = 'Hello!';
export var bye = 'Good Bye!'
// controllers/hello.js
import { hello } from "utils/messages";
export default Ember.Controller.extend({
firstName: 'David',
helloString: Ember.computed('firstName', function(){
return `${hello} ${this.get('firstName')}`;
})
});

Related

Why is my redux store not able to be imported? getting error: "export 'store' was not found in '../../store' [duplicate]

File: SafeString.js
// Build out our basic SafeString type
function SafeString(string) {
this.string = string;
}
SafeString.prototype.toString = function() {
return "" + this.string;
};
export default SafeString;
I have never seen export default before. Are there any equivalent stuff for export default that can be easier to understand?
It's part of the ES6 module system, described here. There is a helpful example in that documentation, also:
If a module defines a default export:
// foo.js
export default function() { console.log("hello!") }
then you can import that default export by omitting the curly braces:
import foo from "foo";
foo(); // hello!
Update: As of June 2015, the module system is defined in §15.2 and the export syntax in particular is defined in §15.2.3 of the ECMAScript 2015 specification.
export default is used to export a single class, function or primitive from a script file.
The export can also be written as
export default function SafeString(string) {
this.string = string;
}
SafeString.prototype.toString = function() {
return "" + this.string;
};
This is used to import this function in another script file
Say in app.js, you can
import SafeString from './handlebars/safe-string';
A little about export
As the name says, it's used to export functions, objects, classes or expressions from script files or modules
Utiliites.js
export function cube(x) {
return x * x * x;
}
export const foo = Math.PI + Math.SQRT2;
This can be imported and used as
App.js
import { cube, foo } from 'Utilities';
console.log(cube(3)); // 27
console.log(foo); // 4.555806215962888
Or
import * as utilities from 'Utilities';
console.log(utilities.cube(3)); // 27
console.log(utilities.foo); // 4.555806215962888
When export default is used, this is much simpler. Script files just exports one thing.
cube.js
export default function cube(x) {
return x * x * x;
};
and used as
App.js
import Cube from 'cube';
console.log(Cube(3)); // 27
What is “export default” in JavaScript?
In default export the naming of import is completely independent and we can use any name we like.
I will illustrate this line with a simple example.
Let’s say we have three modules and an index.html file:
modul.js
modul2.js
modul3.js
index.html
File modul.js
export function hello() {
console.log("Modul: Saying hello!");
}
export let variable = 123;
File modul2.js
export function hello2() {
console.log("Module2: Saying hello for the second time!");
}
export let variable2 = 456;
modul3.js
export default function hello3() {
console.log("Module3: Saying hello for the third time!");
}
File index.html
<script type="module">
import * as mod from './modul.js';
import {hello2, variable2} from './modul2.js';
import blabla from './modul3.js'; // ! Here is the important stuff - we name the variable for the module as we like
mod.hello();
console.log("Module: " + mod.variable);
hello2();
console.log("Module2: " + variable2);
blabla();
</script>
The output is:
modul.js:2:10 -> Modul: Saying hello!
index.html:7:9 -> Module: 123
modul2.js:2:10 -> Module2: Saying hello for the second time!
index.html:10:9 -> Module2: 456
modul3.js:2:10 -> Module3: Saying hello for the third time!
So the longer explanation is:
'export default' is used if you want to export a single thing for a module.
So the thing that is important is "import blabla from './modul3.js'" - we could say instead:
"import pamelanderson from './modul3.js" and then pamelanderson();. This will work just fine when we use 'export default' and basically this is it - it allows us to name it whatever we like when it is default.
P.S.: If you want to test the example - create the files first, and then allow CORS in the browser -> if you are using Firefox type in the URL of the browser: about:config -> Search for "privacy.file_unique_origin" -> change it to "false" -> open index.html -> press F12 to open the console and see the output -> Enjoy and don't forget to return the CORS settings to default.
P.S.2: Sorry for the silly variable naming
More information is in link2medium and link2mdn.
export default function(){} can be used when the function doesn't have a name. There can only be one default export in a file. The alternative is a named export.
This page describes export default in detail as well as other details about modules that I found very helpful.
As explained on this MDN page
There are two different types of export, named and default. You can
have multiple named exports per module but only one default
export[...]Named exports are useful to export several values. During
the import, it is mandatory to use the same name of the corresponding
object.But a default export can be imported with any name
For example:
let myVar; export default myVar = 123; // in file my-module.js
import myExportedVar from './my-module' // we have the freedom to use 'import myExportedVar' instead of 'import myVar' because myVar was defined as default export
console.log(myExportedVar); // will log 123
There are two different types of export, named and default. You can have multiple named exports per module but only one default export. Each type corresponds to one of the above.
Source: MDN
Named Export
export class NamedExport1 { }
export class NamedExport2 { }
// Import class
import { NamedExport1 } from 'path-to-file'
import { NamedExport2 } from 'path-to-file'
// OR you can import all at once
import * as namedExports from 'path-to-file'
Default Export
export default class DefaultExport1 { }
// Import class
import DefaultExport1 from 'path-to-file' // No curly braces - {}
// You can use a different name for the default import
import Foo from 'path-to-file' // This will assign any default export to Foo.
In my opinion, the important thing about the default export is that it can be imported with any name!
If there is a file, foo.js, which exports default:
export default function foo(){}
it can be imported in bar.js using:
import bar from 'foo'
import Bar from 'foo' // Or ANY other name you wish to assign to this import
Export Default is used to export only one value from a file which can be a class, function, or object. The default export can be imported with any name.
//file functions.js
export default function subtract(x, y) {
return x - y;
}
//importing subtract in another file in the same directory
import myDefault from "./functions.js";
The subtract function can be referred to as myDefault in the imported file.
Export Default also creates a fallback value which means that if you try to import a function, class, or object which is not present in named exports. The fallback value given by default export will be provided.
A detailed explanation can be found on https://developer.mozilla.org/en-US/docs/web/javascript/reference/statements/export
One of the good features introduced in ES6 was javascript modules in an efficient way by which we can export and import variables, functions, and classes between different .js files.
We have two different ways to export: Named exports and Default exports. To properly understand the default export, we must first understand the named export well.
Named export
In this case, in the source file, we export the desired variables, functions, or classes that have a specific name. The syntax is as follows:
// file: source.js
export const myVariable = /* … */
export function myFunction() { /* … */ }
export class myClass { /* … */ }
Now, to access the above items in the target file, we must import them as follows:
// file: target.js (in the same directory as the source.js file)
import { myVariable } from "./source.js"
import { myFunction } from "./source.js"
import { myClass } from "./source.js"
Now it's time to get to the main question "what exactly is the default export"?
Default export
Except for the cases where we exported them by name (named exports), there is a similar feature called default export that can be used only once in each .js file. See the following example and compare it with the previous source.js file:
// file: source.js
export default function myNewFunction() { /* … */ }
export const myVariable = /* … */
export function myFunction() { /* … */ }
export class myClass { /* … */ }
In fact, each .js file can have "multiple named exports" and "only one default export"_ here myNewFunction is exported as default. With this, when importing in the target file, javascript understands which item is exported as default.
The item that is "exported as default" (myNewFunction) is imported in the target.js file as follows:
// file: target.js (in the same directory as the source.js file)
import anyName from "./source.js"
Look carefully at the differences! Here, we don't have { } sign after import, and we used a custom name that we didn't have in the source file. Here anyName represents myNewFunction.
This shows that we can give "any desired name" to the item that is "exported as default" when importing it and just pointing to the "path" of the source file, JavaScript will find that file and import it.
Some important notes:
Unlike named exports, in default export we don't need to export named
items and we can export "unnamed" items as well.
Why did they add the Default export feature to ES6 at all!? for the ability
to export "unnamed items" (anonymous functions and classes) as well as
expressions and even object literals in addition to named items.
In ES6 there are two kinds of exports:
Named exports - for example export function func() {} is a named export with the name of func. Named modules can be imported using import { exportName } from 'module';. In this case, the name of the import should be the same as the name of the export. To import the func in the example, you'll have to use import { func } from 'module';. There can be multiple named exports in one module.
Default export - is the value that will be imported from the module, if you use the simple import statement import X from 'module'. X is the name that will be given locally to the variable assigned to contain the value, and it doesn't have to be named like the origin export. There can be only one default export.
A module can contain both named exports and a default export, and they can be imported together using import defaultExport, { namedExport1, namedExport3, etc... } from 'module';.
export default is used to export a single class, function or primitive.
export default function() { } can be used when the function has no name. There can only be one default export in a file.
Read more

Import, rename, and export a function in JavaScript?

With JavaScript what's the shortest way to import a named export, rename it, and export it again?
This code works but it feels more verbose than it should be
import { mock as myFunctionMock } from 'context/myFunction';
export const myFunction = myFunctionMock;
You can combine the import and export like so:
export { mock as myFunctionMock } from 'context/myFunction';
See MDN Docs
Note that you won't actually be able to use myFunctionMock within your code file since you haven't imported it. Neither mock nor myFunctionMock will be defined within this module.
This is a useful shorthand when you're building a library that will be used by other modules or by your end-user.
For example, if you had a utils library that you wanted to export, but you wanted to organize your util functions across several smaller files, such as stringUtils, objectUtils, dataUtils, etc, you can export the contents of those modules within your utils module to create a single, monolithic access point:
stringUtils.js
export function toLower(){}
export function toUpper(){}
objectUtils.js
export function propertyMap(){}
utils.js
export {
toLower as stringToLower,
toUpper as stringToUpper,
} from "stringUtils.js";
export {
propertyMap as objectPropertyMap
} from "objectUtils.js";
I wouldn't generally recommend this approach for internal code as it can make your dependency trees a bit wonky in some cases. It can, however, be extremely useful in situations where you want to import from a common interface but the implementation is dependent on the build (prod vs dev, web vs node, etc)
import { mock as myFunction } from 'context/myFunction';
export { myFunction };
in your original exporter, do:
module.exports = { mock: function () {...}}
When importing, do:
const myFunctionMock = require('file path of exporter');
then to reexport in the same file:
module.exports = {renamedMock: myFunctionMock};
Now any changes to mock will propagate to the other modules where it's referenced (side note, this is node.js in a nutshell).

ES6 Imports inside Export default

I'm currently migrating the whole code of a NodeJS application from ES5 to ES6/7.
I'm having trouble when it comes to imports :
First, I understood that making an import directly call the file. For example :
import moduleTest from './moduleTest';
This code will go into moduleTest.js and execute it.
So, the real question is about this code :
import mongoose from 'mongoose';
import autopopulate from 'mongoose-autopopulate';
import dp from 'mongoose-deep-populate';
import { someUtils } from '../utils';
const types = mongoose.Schema.Types;
const deepPopulate = dp(mongoose);
export default () => {
// DOES SOMETHING USING types AND deepPopulate
return someThing;
};
export const anotherModule = () => {
// ALSO USE types and deepPopulate
};
Is this a good practice to have types and deepPopulate declared outside of the two exports ? Or should I declare them in each export ?
The reason of this question is that I'm having a conflict due to this practice (to simplify, let's say that dp(mongoose) will call something that is not declared yet)
You can only have one 'default' export to a module, or you can have multiple 'named' exports per module. Take a look at the following for a good description of handling exports in ES6: ECMAScript 6 Modules: The Final Syntax

Importing external dependencies in Typescript

I am a newbie in typescript/node. I have a typescript file "order.ts" from which I would like to import an external config dependency from "config.ts"
My config file code is as below
let config = {
mongoAddress: "mongodb://localhost:27017/dts",
dataDirectory: "../../data/"
};
module.exports = config;
I am importing the config file in the order file as below
import { config } from "../../config";
However I am getting the TS compiler throwing error "... file not a module". Any clues how I should I be importing my external dependency in typescript
The main part here is you want to export your object instance. You're on the right track with that, but there may be an easier way for you.
In this case something like wrapping it in a class and exporting that:
export class Config {
mongoAddress = 'mongodb://localhost:27017/dts';
dataDirectory = '../../data/';
}
Notice the export before class. The same can be applied to interfaces, enums etc. By exporting it this way you can then import it and initialise it:
import { Config } from '../config';
var c = new Config();
console.log(c.mongoAddress);
This will not make it a variable, like in your original example, but you'll simply wrap it in a class. This is also why you have to initialise it first using new Config().
Now, I'm assuming you want these properties simply to be accessed globally. And perhaps even static/readonly, so you don't have to initialise the class each time. Making use of the static typing of TypeScript, the sample would in this case be better refactored to something like this:
export class Config {
public static readonly mongoAddress: string = 'mongodb://localhost:27017/dts';
public static readonly dataDirectory: string = '../../data/';
}
With this, calling it is even less obtrusive - and very type safe:
console.log(Config.mongoAddress);
console.log(Config.dataDirectory);
Now exporting this way is just one of the options. It actually depends entirely on the library structure you're using throughout your application (or from third partie libraries, for that matter). It's a bit of dry reading, but I recommend you have a look at the different structures to get acquainted with terms like UMD and modules and how they relate to an import.
Hope this helps!
There are 2 ways you can do import and export.
1) default export
// config.ts
export const config = {
mongoAddress: "mongodb://localhost:27017/dts",
dataDirectory: "../../data/"
};
export default config;
// your other file
import configs from './config';
Note: Here you can give any name for the imported module;
2) normal export with exact declaration name while importing.
// config.ts
export const config = {
mongoAddress: "mongodb://localhost:27017/dts",
dataDirectory: "../../data/"
};
// your other file
import { config } from './config';
Note: Here you have to give the exact name of the module that you exported.
Best practices to follow while exporting configs.
create a static class with static variables in the code. Which likely means that these configs are fixed stuffs.
module.exports is the node syntax for exporting modules. Typescript has a keyword names export so you can just use this:
export const config = {
mongoAddress: "mongodb://localhost:27017/dts",
dataDirectory: "../../data/"
};

Why does generated ember cli helper export function and helper?

By default a helper generated by ember-cli looks like this:
import Ember from 'ember';
export function boundLoc(input) {
return input;
}
export default Ember.Handlebars.makeBoundHelper(boundLoc);
I have two questions to better my understanding of this code.
1) Why is there two exports? Does the first export allow the helper to be imported and used by other JavaScript files, whereas the second export is what actually registers it as a Handlebars helper?
2) Secondly, if the code looked like:
import Ember from 'ember';
export default Ember.Handlebars.makeBoundHelper(function boundLoc(input) {
return input;
});
would this export it as a Handlebars template helper but not make the boundLoc() method accessible to other JavaScript files that imported this helper?
1) Yes, there are two exports so that the helper can be used as a function from within other JavaScript after it is imported and as a handlebars helper.
In other JavaScript:
import {
boundLoc
} from 'app/helpers/boundLoc';
boundloc(input);
and in a template:
{{boundloc input}}
2) Yes, the behavior you described is accurate. That would only export a boundHelper and not the function for consumption elsewhere. You can always try a POC.
Note, however, that you may have trouble with generated tests if you try to only export the boundHelper. See this answer for more details.

Categories

Resources