I need to use this NoSleep.js inside my AngularJs controller. I installed NoSleep using bower but I need to inject it to my angularjs controller, but I have no idea on how do it, NoSleep isn't an angular service and I need to use this declaration var noSleep = new NoSleep(); in order to use it.
I'm using babel, webpack, gulp, karma
Any advise?
Typically when using non-angularjs libraries in an Angularjs application they are wrapped in a module. Then you inject the module into your app and then inject the service/factory you've wrapped with this into your controllers as needed, so you'd create a module that looks something like this:
(() => {
"use strict"
angular.module('nosleep.module', []).factory('nosleep', ['', function () {
return new NoSleep()
}])
})()
Then you'd inject the module into your main application module with something like:
angular.module('myApp', '[nosleep-module')
Then in your controllers that require access to nosleep you'd inject nosleep.
class myController {
constructor(nosleep) {
this.nosleep = nosleep
}
}
Then from within your control your can address it with this.nosleep.
It looks like NoSleep just declares a function in the global scope, so you could do something like this:
NoSleepService.js
(function () {
// place noSleep minified code here
angular.module('myApp').service('noSleep', NoSleep);
})()
That will create a NoSleep object within the enclosing function so that it doesn't pollute the global scope and register a new instance of it to your angular app.
If you have any JS lib and it's not an Angularjs lib, just add it using script tag in the html file and call it like you used to before they create AngularJs.
Have you tried it ?
Or go to the other way and wrap the lib with AgnularJs service (write an AngularJs service and call the lib method inside it), then inject this new service anywhere you want.
Update:
What #Mike Feltman and #richbai90 said in their answers was good and maybe enough for you, but I think it's better to build your service and call a methods you created, but inside these method use what ever library you want (it'll be like using interfaces in C#):
(function() {
'use strict';
angular.module('nosleep.module', []).service('nosleep', ['', nosleepFunc]);
function nosleepFunc() {
var nosleepObj = new NoSleep();
var service = {
method1: method1,
method2: method2
//... etc
};
function method1() {
return nosleepObj.method1();
}
// ..... other methods
return service;
}
})();
This way if you wanted to change nosleep lib to another one, and that new one lib has another method names, you need only to change in your service code.
Related
I have two third-party modules, both defining a factory with the same name. Obviously, I don't have any control over the naming of those modules without resorting to a kludge.
Additionally, I have two further, internal modules, each using a different one of the two third-party modules as a dependency (as below). I was sure that I was unable to access components from a module not listed in current module's dependencies, but it turned out I was wrong.
Here even if own1 depends on thirdParty1 (which has hello defined as hello world) it's getting hi there (from thirdParty2) in controller. The same is for the other modules' pair.
Is there any way to "isolate" modules so I can only use stuff that I explicitly depend on? If not, what's the point of having modules if I can reach anything at any time (assuming main app module has it as its dependency)? Also if I have two modules with components named hello how can I tell which is gonna be used?
Here is jsbin for that http://jsbin.com/vapuye/3/edit?html,js,output
angular.module('app', ['own1', 'own2']);
//third-party modules
angular.module('thirdParty1', []).factory('hello', function () {
return 'hello world';
});
angular.module('thirdParty2', []).factory('hello', function () {
return 'hi there';
});
// "own" modules
angular.module('own1', ['thirdParty1']).controller('Own1Ctrl', function(hello) {
this.greet = hello;
});
angular.module('own2', ['thirdParty2']).controller('Own2Ctrl', function(hello) {
this.greet = hello;
});
And the result of:
<body ng-app="app">
<div ng-controller="Own1Ctrl as own1">
Own1: {{ own1.greet }}
</div>
<div ng-controller="Own2Ctrl as own2">
Own2: {{ own2.greet }}
</div>
</body>
Is :
Own1: hi there
Own2: hi there
You can request a factory of a certain module explicitly (without dependency injection):
var injector = angular.injector(['thirdParty1']);
var hello1 = injector.get('hello');
var injector = angular.injector(['thirdParty2']);
var hello2 = injector.get('hello');
You can also use this, to wrap the third party factories into own factories:
angular.module('own1', ['thirdParty1']).factory('hello1', function () {
var injector = angular.injector(['thirdParty1']);
var hello = injector.get('hello');
return hello;
});
angular.module('own2', ['thirdParty2']).factory('hello2', function () {
var injector = angular.injector(['thirdParty2']);
var hello = injector.get('hello');
return hello;
});
This allows you to use hello1 and hello2 in all other parts of your application.
Since there is no built-in name spacing of modules (or components of modules) the best way to achieve your goal is to use a unique naming convention for your modules. Most libraries for angular do this, and then you should be good to go.
Besides encapsulating your applications behavior, modules help testing and mocking your application.
I dont think it is possible for angular to differentiate between two components that are named the same (I think this changes with angular 2). And I might argue that two components that are named the same might do the same and you should look why you need both?
I'm pretty new to Angular. Sorry for the basic question but I couldn't find info about how to write a library in Angular the proper way.
The reason is to benefit from Angular modules as well as testability/mocks.
The library
I am transferring my code to Angular but a big part of my code is written based on a library that I've developed over a couple of months. Imagine something like underscore.
So my initial thought was to wrap it in an angular module like:
angular.module('mylib', [])
.factory('map', map)
.factory('reduce', reduce)
.factory('find', find);
function map (...
Each factory function is testable and stuff. And then use it like:
angular.module('app', ['mylib'])
.controller('MainCtrl', ['$scope', 'map', MainCtrl]);
function MainCtrl($scope, map) {
... do stuff with map ...
This is fine for a couple of functions I guess but my library has over 20 functions and it's just too much boilerplate to define every one of them as a factory and then inject them into my controller.
Second solution
Another way is to have just one factory that returns an object. Kinda like this:
angular.module('mylib', [])
.factory('mylib', mylib)
function mylib () {
var exports = {};
exports.map = function (...
exports.reduce = function (...
exports.find = function (...
return exports;
}
And then use it like this:
angular.module('app', ['mylib'])
.controller('MainCtrl', ['$scope', 'mylib', MainCtrl]);
function MainCtrl($scope, mylib) {
... do stuff with mylib.map ...
But...
Is this a good approach? What would a good way to write a utility library in Angular and use it? Readability and maintainability are important but I prefer not to have so much boilerplate code.
If your library functions are as generic as your example, I wouldn't try to define them as Angular modules in the first place. Write a plain JS library. That will result in less useless boilerplate, and as a bonus your library will also be usable in non-Angular apps. Angular plays along nicely with libraries that are unaware of it, for example by not requiring data objects to implement anything extra (think ko.observable, Backbone Model, etc) to be usable with data binding.
Being an Angular module is not a requirement for testability. The only thing I can think of that Angular could do to improve testability in a generic utility library is the dependency injection (e.g. injecting a mock service for "current time" into a time library for deterministic results). If you don't need any of that, take the past of least complication and just write a plain JS library.
If wrapping the library in an Angular module is an absolute requirement (for instance to not pollute the global namespace with a short namespace for it), I would still write the library in plain JS, put it into a more complicated namespace, and then alias it with an Angular module.
lib/handy-utilities-1.0.js
// Or any other descriptive namespace
var handyUtilities = {
map: function() { ... }
};
app/util.js
angular.module("handyUtilities", []).constant("util", handyUtilities);
As suggested I wrap all my services into a module, So, I created files to organize them:
myServicesModule.js
var myServices = angular.module('myServices', []);
serviceA.js
myServices.service('serviceA', function(){...});
and serviceB.js
myServices.service('serviceB', function(){...});
etc etc.
As a good practice, we should try to avoid global variables, so is there any way to avoid declaring a global var myServices by something I guess module resolving by name? I understand by putting all services into a single file could solve this issue, but I don't want to create a huge file.
Second parameter of module function (dependencies array) is optional :
If you set the second parameter, it will create the module (and override any existing module with the same name) :
// Create the module
angular.module('foo', []).controller('FooCtrl', function($scope) {
// ...
});
If you do not set the second parameter, it will retrieve the module by its name and fail if module does not exist :
// Retrieve module by its name and fail if module does not exist.
angular.module('foo').controller('FooCtrl', function($scope) {
// ...
});
The angular.module is a global place for creating, registering and
retrieving Angular modules. All modules (angular core or 3rd party)
that should be available to an application must be registered using
this mechanism.
When passed two or more arguments, a new module is created. If passed
only one argument, an existing module (the name passed as the first
argument to module) is retrieved.
So this will work:
angular.module('myServices', []);
angular.module('myServices').service('serviceA', function(){...});
angular.module('myServices').service('serviceB', function(){...});
You don't need create variable for your service. It's possible tot do it that way`(in different files):
For example, file1.js:
angular.module('myServices', []);
file2.js
angular.module('myServices').service('serviceA', function(){...});
I can do this in node.js
var module = require('../path/module')
module.functionname()
So I thought I'd like to do that in client side Javascript to organize things slightly.
So each of my files now has a namespace. So say login.js has a namespace login.
My question is, what's the best way in ECMAScript 5 to implement something alongs these lines?
What you are trying to achieve can be done with AMDs (asynchronous module definitions). Check out RequireJS for that: http://requirejs.org/
With Require.js you can basically define a set of dependencies, let them get loaded asynchronously and execute code once all stuff was loaded nicely:
require(['dependency1.js', 'dependency2.js'], function(dep1, dep2) {
console.log(dep1.functionname())
})
The dependency will then declare it's functionalities with require's define method:
define(['a/possible/dependency.js'], function() {
return {
functionname: function() { return 1 }
}
})
I'm building an app that has a single global namespace like so:
var myApp = {};
I then have a bunch of different reusable "modules" comprised of models, views and controllers.
//Bar chart module code
org.example.chart.bar.module
org.example.chart.bar.model
org.example.chart.bar.view
org.example.chart.bar.controller
I also have a big dataSource singleton and a dataManager for loading data to the dataSource:
org.example.data.dataSource
org.example.data.dataManager //populates the dataSource with CSV data
And finally translation strings and settings that should be available across the app:
org.example.static.translations
org.example.static.settings
How would you (re-)organize this so that I have easy access to the application level singletons (such as dataSource, dataManager, translations etc.) and can easily instantiate reusable modules that get scoped under the current application instance?
(Would you for example, already from the beginning, use the same namespace for your "classes" and your app? Or would you perhaps make references like so: myApp.translations = org.example.static.translations?)
No we don't namespace. We write modular code and we use module loaders.
Example of a module loader would be require.js or browserify or seajs.
And an example module would be something like:
(function () {
var jQuery = require("jQuery");
var chart = require("chart");
...
define("moduleName", moduleObject);
})();
There is nothing stopping you adding another name to the class. For example.
org.ds = org.example.data.dataSource;
then you can call
org.ds.getDatasource();
instead of
org.example.data.dataSource.getDatasource();
but both will still work.
EDIT: You could also create other simpler functions that call it taking it out of the oo structure
var dataSource = function () { return org.example.data.dataSource.getDatasource(); };
Consider using something like RequireJS for organizing your modules.
Some excellent resources from Addy Osmani :
http://addyosmani.com/largescalejavascript/
http://addyosmani.com/blog/large-scale-jquery/
http://addyosmani.com/resources/essentialjsdesignpatterns/book/