How to create a JS file with a variable name in AngularJS? - angularjs

How can I include a JavaScript file in my Angular project but assign a name to all of its functions? I just included Underscore.Script and Lodash for the first time and noticed they both have actual names ("_" and "s")..
_.mixin(s.exports());
I've watched a few courses on JavaScript and Angular but cannot find anything that actually explains this or how to accomplish it.

In Javascript, the simplest way is when writing your library define all of your functions as properties of an object in the global scope.
var myLibrary = {};
myLibrary.myFunction = function(){
/* Your function code */
};
Then after including your file, you can access your functions like so:
myLibrary.myFunction();
A better way might be to wrap your library in a self executing function, which will help you avoid unintentionally adding properties to the global scope (a good practice)
(function(root){
var myLibrary = {};
myLibrary.myFunction = function(){
/* Your function code */
};
root.myLibrary = myLibrary;
}(window));
Please note that passing window to the self-executing function will work in the browser, but not in a different context (like nodejs).
If you want to create something specifically for Angular, I would suggest looking into angular services which is how you can create libraries that work with the Angular dependency-injection system.

in angular we have controllers, directives, services, factories and providers.
Lets take an example of Factory - "Customer" having function to get and set details.
app.module.js
angular.module("myapp", []);
Customer.js
angular.module("myapp").factory("Customer", function(){
function Customer(name, email){
this.name = name;
this.email = email;
}
Customer.prototype.getName = function(){
return this.name;
};
Customer.prototype.getEmail = function(){
return this.email;
};
Customer.prototype.setName = function(name){
this.name = name;
};
Customer.prototype.setEmail = function(email){
this.email = email;
};
});
CustomerController.js
angular.module("myapp").controller("CustomerController", ['Customer',
function(Customer){
var custObj = new Customer();
custObj.setName("Test");
custObj.setEmail("test#gmail.com");
console.log("Name: " + custObj.getName() + " Email: " + custObj.getEmail());
}
]);
Here app.module.js -- Angular App main module is initialised.
Customer.js is a JS and you can use this file and its functions by giving it a name "Customer" in CustomerController.js file.

Other answers tell you to make your own scripts modular. This is good, but it doesn't solve the problem of disambiguating Underscore and LoDash. So here's how to do that:
I would first recommend that you look into modular systems like RequireJS. Libraries like LoDash and Underscore are built to recognize and integrate with AMD style architectures, allowing them to coexist (however, these two libraries are redundant. LoDash is supposed to be a drop-in replacement for Underscore. But I digress.
If you do not use a module system (not to be confused with angular's module), you'll have to do the shim work yourself. It isn't hard, by any means, but it's a bit manual. Scripts specified in your HTML are executed in-order (caveat: there are asynchronous loaders out there, but they make your problem easier to solve, not harder).
So, for your particular problem, you can do this:
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/3.8.0/lodash.js"></script>
<script>
var mylodash = _;
</script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore.js"></script>
<script>
var myunderscore = _;
</script>
You will thereafter have access to both (feel free to name or group them however you'd like). Both of these libraries do a good job of not polluting the global namespace (which is attached to window in a browser). But if your library exposes lots of different methods, you'll need to cobble them all together yourself.
Simple? Sure, but in the long run, learn to use something like CommonJS or RequireJS. They not only solve this particular problem, but they also provide so many other benefits -- you'll be glad you did.

Related

Why requireJs wouldn't load defined dependency modules?

I am having problem while using Require.js to load dependencies for my module. Basically I have following module in which I define extension of Backbone Model.
define(["models/services/ProjectServices"],
function (ProjectServices) {
var SomeModel = Backbone.Model.extend({
sample: function () {
var servicesFromDependency = ProjectServices; //undefined
var projectServices = window.require.s.contexts._.defined["models/services/ProjectServices"]; //defined and Ok
}
});
return SomeModel;
}
);
In this module I want to use already defined ProjectServices module. In order to do that I add it as a dependency. The thing is that within defined sample function ProjectServices is showing as undefined. But if I look directly into require defined modules it is showing there correctly and I can use it (although I do not want as I don't like to hack it this way). To add more context, I am also using this ProjectServices dependency on other module and there it is loaded properly through define function.
Any suggestions on why module would not be loaded?
Try this inside a module:
var ProjectServices = require('models/services/ProjectServices');
I think in many situations, there is no need for window global assignment and I try to avoid while using requirjs.
The only thing I can come up with is a possible circular reference, meaning that two modules require each other (which should not be the case).
As you say that the require works well in other modules, it should not be due to a missing return statement in the required module, or a wrong path. (You might check this anyway).

Place of the helper functions in Backbone

I've got some functions like this:
function killOrphans(str) {
return str.replace(/\s([\dwuioaz]{1})\s/gi, ' $1\u00a0');
}
which is generally a helper function to remove single letter words (orphans) from the end of a line (Polish typography demands to do this).
Question: how do you treat a library of such functions? A module in the global scope? extending jQuery? Extending the prototypes of String, Array etc.? (I don't think it's a good idea...). I think I'll go in the direction of underscore and create a module, but I'd be glad to hear real life examples of your way to do it.
Adam
In my project, I've used a variety of strategies for helper functions.
Extra methods on a view or a model.
var MyView = Backbone.View.extend({
initialize: function(){...},
render: function(){...},
helper: function(){...}
});
Use a helper module.
var myHelpers = {
foo: function(){...},
bar: function(){...},
baz: function(){...}
};
Extend an existing lib.
jQuery.fn.foo = function(){...};
Use an IIFE (best for functions you'd like to keep private)
var MyView = Backbone.View.extend({
initialize: function(){...},
render: function(){...},
myMethod: (function(){
function helper(){...}
return function(){
// do stuff here, using helper()
}
})()
});
Also, if you're not working in node.js which automatically provides a module system, it's worth using some strategy, such as browserify or requirejs, to export and import modules in a sane way, rather than having everything hang off the global namespace.
It is a question for Nobelprize - how to structure Javascript code with such a dynamic language. There are a lot of patterns and library solutions for this problem. For example:
You can extend prototype but then you are creating coupling. You can
create a module, but do you need module for one function ? You can
use Requirejs, annonymous functions...
Best real life examples are in production code. Take a look how jQuery deals with structure. And also Backbone. Try to learn classic design patterns - they are source of gold for any JS developer.
My advice is to dig deeper into JS and discover why language is designed in such a way. My first language was Javascript but I didn't make any progress until I started to learn something more traditional like in OO sense.

How do I write a custom module for AngularJS?

I need to write a custom module for AngularJS, but I can't find any good documentation on the subject. How do I write a custom module for AngularJS that I can share with others?
In these situations were you think that the docs can't help you any more, a very good way to learn is to look at other already-build modules and see how others did it, how they designed the architecture and how they integrated them in their app.
After looking at what others did, you should have at least a starting point.
For example, take a look at any angular ui module and you will see many custom modules.
Some define just a single directive, while others define more stuff.
Like #nXqd said, the basic way to create a module is:
// 1. define the module and the other module dependencies (if any)
angular.module('myModuleName', ['dependency1', 'dependency2'])
// 2. set a constant
.constant('MODULE_VERSION', '0.0.3')
// 3. maybe set some defaults
.value('defaults', {
foo: 'bar'
})
// 4. define a module component
.factory('factoryName', function() {/* stuff here */})
// 5. define another module component
.directive('directiveName', function() {/* stuff here */})
;// and so on
After defining your module, it's very easy to add components to it (without having to store your module in a variable) :
// add a new component to your module
angular.module('myModuleName').controller('controllerName', function() {
/* more stuff here */
});
And the integration part is fairly simple: just add it as a dependency on your app module (here's how angular ui does it).
angular.module('myApp', ['myModuleName']);
If you want to look for a good example, you should look into the current module written in angularJS. Learn to read their source code. Btw this is a structure that I use to write modules in angularJS:
var firstModule = angular.module('firstModule', [])
firstModule.directive();
firstModule.controller();
// in your app.js, include the module
This is the basic one.
var newMod = angular.module('newMod', []);
newMod.controller('newCon', ['$scope', function ($scope) {
alert("I am in newCon");
$scope.gr = "Hello";
}]);
Here newMod is a module which has no dependencies [] and has a controller which has an alert telling you are in the controller and a variable with value hello.

From two ways of Creating AngularJS Controllers which should be used and why?

In most demos below method is given
First Method:
function MyCtrl( $scope ){
$scope.someValue = "All your base are belong to us!";
}
Second Method:
app.controller("MyController",funciton( $scope ){
$scope.someValue = "All your base are belong to us!";
});
What are the pros and cons of using either method?
I'll try to give a quick summary each options pros and cons.
1) The following version is often used in examples around the web because it's easy to write. I wouldn't recommend it in real code however, for two reasons. First of all it can break horribly if you minify your code (and you should), secondly you are littering with globals which is generally bad form and encourages sloppy dependencies that are hard to test.
function MyCtrl( $scope ){
$scope.someValue = "All your base are belong to us!";
}
2) The second version you wrote is better. It contains the function on the app which is good, but it can still break from some minifiers.
app.controller("MyController",function( $scope ){
$scope.someValue = "All your base are belong to us!";
});
3) To make it better, lets do this instead. Note that the function is now inside a list with its dependencies. This "double" naming of the dependencies helps angular keep track of things in minified code.
app.controller("MyController", ['$scope', function( $scope ){
$scope.someValue = "All your base are belong to us!";
}]);
4) You can also inject your dependencies after your controller, something like this. This should also be safe from minifiers as far as I know (I haven't used this version myself).
app.controller("MyController",function( $scope ){
$scope.someValue = "All your base are belong to us!";
}).$inject = ['$scope'];
So 3 and 4 are the best ones. They survive minifying and they allow you to easily mock out any dependency when writing tests. As far as I know the difference between 3 and 4 is cosmetic so both should work equally fine. I personally use 3, I think it looks slightly nicer :)
I would highly recommend the second one.
The reason behind this is minification. Angular will try to match the controller's name you call in the templates via ng-controller, e.g.:
<div ng-controller="Controller">
<!-- [...] -->
</div>
Suppose you have a controller like this:
function Controller($scope) {};
and minify it (with some minifiers), you'll get an output like this:
function c(s) {};
Quick EDIT: I checked it with uglify - it will preserve your function name (and you'll be fine), I used a maven based minifier in a project of mine, which actually mangled the method names (I guess I have to replace it)
Your app might just break from that.
Therefore it is recommended to use strings as identifiers for controllers (and injections, etc.) like this:
var app = angular.module("module", []);
app.controller("Controller", ['$scope', function(scope) {
}]);
This will stop a minifier from breaking the app. The reason to put injections like this is as follows:
var app = angular.module('module',[]);
function Ctrl($scope, $location) {
$scope.test = 42;
};
will get minified to (by UglifyJS):
function Ctrl(a){a.test=2}var app=angular.module("module",[])
and Angular will not know that you need the $scope here.
If minification does not matter to you, you can use either one, as the question really just breaks down to maintainability and readability. Also, if you have multiple modules with controllers, the second one will not get you into trouble.
The difference is that the second version defines the controller in your app space. Thus the app.controller call. Difference is that afaik you can only use the controller inside of an ng-app="yourApp" instead of everywhere on the site.
Personally, I like more the 2nd method, because it is easier to review the code and it is more maintainable, those are just my thoughts.But with 1st method you can put it as a controller in other apps.
Here is what I found from
http://www.bennadel.com/blog/2421-Creating-AngularJS-Controllers-With-Instance-Methods.htm
In most AngularJS demos, you will see Controllers being defined as free-standing JavaScript functions:
function MyCtrl( $scope ){
$scope.someValue = "All your base are belong to us!";
}
These functions are then referenced in the View using the ngController directive:
<div ng-controller="MyCtrl">
{{ someValue }}
</div>
NOTE: You should never ever abbreviate "Controller" as "Ctrl". I am only doing that here because this it is what you will typically see in a demo. You should try to avoid abbreviations as much as humanly possible when naming things in programming.
The expression used to define the ngController directive is the name of the Controller in your dependency injection (DI) framework. In an AngularJS application, the dependency injection framework is provided directly by AngularJS. This means that, rather than using a free-standing function, we can use the AngularJS controller() method to define our Controllers:
// Define "MyController" for the Dependency Injection framework
// being used by our application.
app.controller(
"MyController",
funciton( $scope ){
$scope.someValue = "All your base are belong to us!";
}
);
Here, we are defining the controller as an identifier - MyController - and a constructor function. And, once we can do this, we can get much more fine-tuned in how we actually define our constructor function.

How do I use namespaces in Backbone with RequireJs

I am unsure how I use namespaces in an modularized (RequireJs) Backbone environment.
I have thought a bit how it could look like but am totally unsure if this is the right way.
app.js (getting executed by main.js)
define('App', ['underscore', 'backbone', 'Router'], function( _, Backbone, Router){
function initialize(){
var app = {}; // app is the global namespace variable, every module exists in app
app.router = new Router(); // router gets registered
Backbone.history.start();
}
return { initialize: initialize }
});
messages.js
define('MessageModel', ['underscore', 'backbone', 'App'], function(_, Backbone, App){
App.Message.Model; // registering the Message namespace with the Model class
App.Message.Model = Backbone.Model.extend({
// the backbone stuff
});
return App;
});
Is this the right approach or am I fully on the wrong way (if yes please correct me!)
Have a look at the TODO Backbone + requireJs example:
https://github.com/addyosmani/todomvc
Found an real example app using namespaces like mentioned in the start post: https://github.com/nrabinowitz/gapvis
Just have to test it the next days
I'm new to backbone, but just read a snippet from the requirejs docs.
A module is different from a traditional script file in that it defines a well-scoped object that avoids polluting the global namespace. It can explicitly list its dependencies and get a handle on those dependencies without needing to refer to global objects, but instead receive the dependencies as arguments to the function that defines the module. Modules in RequireJS are an extension of the Module Pattern, with the benefit of not needing globals to refer to other modules.
To me, this sounds as if when using requirejs, you can forget all about namespaces, as requirejs takes care of it. You would just have access it differently. When you want to access it from another module, you'd put a path to the file in your array of dependencies, and and feed a respective variable to the following function.
define(["folder/a-script", "folder/another-script"], function(AScript, AnotherScript) {
// In here the scripts are loaded and can be used, but are called by
// their relative name in the anonymous function.
}
);
Anyway, perhaps in some cases there is still a need to namespace something, but I think in general, it's worth reading the docs to see if you need to.

Resources