Include multiple module in angularjs - angularjs

I have a module like this :
var master = angular.module('master', ['DataService'])
master.controller('MasterController', function ($scope, MasterOp) {
$scope.status;
$scope.reports;
$scope.data = {
singleSelect: "all",
flag : "true"
};
$scope.filter = function() {
$scope.data.flag = "false";
};
$scope.groupBy = {
pubid : "false",
sid : "false",
device : "false"
};
$scope.getMasterReports = function() {
$scope.user = JSON.parse(sessionStorage.response);
//alert($scope.groupBy.pubid+"ak");
MasterOp.getMasterReport($scope.sdate,$scope.edate,$scope.user.pubProfile.pubid,$scope.groupBy.pubid,$scope.groupBy.sid,$scope.groupBy.device)
.success(function (data) {
$scope.reports = JSON.parse(data.report);
$scope.metrics= $scope.user.pubProfile.metrics;
})
.error(function (error) {
$scope.status = 'Unable to load customer data: ' + error.message;
});
};
$scope.logout = function(){
window.location.href="/AnalyticsMaster/index.html";
};
$scope.tab2 = function()
{
$scope.groupBy.sid="true";
$scope.groupBy.pubid="false";
$scope.data.flag = "true";
$scope.data.SingleSelect = "all";
$scope.reports=null;
$scope.getMasterReports();
};
$scope.tab3 = function()
{
$scope.groupBy.pubid="true";
$scope.groupBy.sid="false";
$scope.data.SingleSelect = "all";
$scope.data.flag = "true";
$scope.reports=null;
$scope.getMasterReports();
};
$scope.tab1 = function()
{
$scope.groupBy.pubid="false";
$scope.groupBy.sid="false";
$scope.data.flag = "true";
$scope.data.SingleSelect = "all";
$scope.reports=null;
$scope.getMasterReports();
};
});
When i trying to add more module in this it stop working. I am not able to understand why its happening.
For Example if i add like this its not working even adding any other module also its stop working.
var master = angular.module('master',['myApp','DataService'])
var master = angular.module('master',['ui.directives','ui.filters','DataService'])
Both cases it stop working. Please help me to understand what i am doing wrong.

Index.html
when adding multiple modules in your project make sure you have a ref to it in your index html. like this
<!-- Angular Modules -->
<script type="text/javascript" src="app/app.module.js"></script>
<script type="text/javascript" src="app/app.routes.js"></script>
<script type="text/javascript" src="app/components/home/homeCtrl.js"></script>
Or non custom modules
<!-- Angular links -->
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.5/angular.js"></script>
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.5/angular-animate.js"></script>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/angular-ui-router/0.2.15/angular-ui-router.js"></script>
Its the same as adding any script.
Main Module
The second thing you do is add them to your main module like this
var app = angular.module("myApp", [
'ui.bootstrap',
'ngAnimate',
'myAppRouter',
'myAppHomeCtrl',
'myAppHomeService',
'myAppNavbarDirective',
'myAppNavbarService',
'myAppLoginCtrl',
'myAppLoginService'
]);
Live Example
The best practice in angular is to create a module for each of your features. I've been working on a project here is a link to the project, feel free to fork or clone it to get a good look at the structure.

You are declaring the same module name repeatedly.
You only declare a module once. The module function requires the second argument for dependency array when you declare it.
After that when you want to add components to that module you use the module getter which doesn't have the dependency array argument
// declare a new module
angular.module('master', ['DataService']); // has another module dependency
// add components to existing module
angular.module('master').controller(....;
// add the dependency module shown in "master"
angular.module('DataService', []);// might also have different dependencies here

Related

why factory don't work properly between the directives?

I make two directives .To communicate between two directives I used a factory .
but it not work properly ..I want to delete my text when I press delete button ..I take factory to do my task but it not working .I also try to take service .it also don't help
here is my code
http://plnkr.co/edit/Yenmira9J9XpjscQzRoX?p=preview
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="style.css">
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"></script>
</head>
<body ng-app="app">
<a></a>
<b></b>
<script>
angular.module('app',[]).directive('a',function(){
return {
restrict :'E',
scope:{},
templateUrl:'a.html',
controller:'ts',
controllerAs:'vm'
}
}).controller('ts',function(sharedService){
var vm=this;
vm.delete=function(){
alert('--');
sharedService.deletepro();
}
}).directive('b',function(){
return {
restrict :'E',
scope:{},
templateUrl:'b.html',
controller:'bb',
controllerAs:'vm'
}
}).controller('bb',function(sharedService){
var pm=this;
pm.message= sharedService.sendData();
}).factory('sharedService', function() {
var data = {};
function deletepro(){
data = {};
}
function sendData(){
var obj = {name:"pQr"};
data = obj;
return data;
}
return {
sendData: sendData,
deletepro: deletepro
};
});
</script>
</body>
</html>
After your controller is first initialized, data and vm.message reference the same object, but when you run deletepro then data references a new object, but vm.message still references the old one.
If you want to pass data in this way, you must never replace data with a new object (otherwise, controllers will have to get the new object again).
Instead of data = {};, try data.name = '';
It looks like you're expecting that it will update because data is a shared reference. But you are resetting it to {}, which breaks the reference. You instead need to modify it:
function deletepro(){
for(var prop in data){
delete data[prop];
}
}
Also, keep in mind a and b are both real html tags, not sure if there are any issues ovewriting the standard ,

Opencpu and Meteor

I have seen some examples of using opencpu together with angular, but no examples of using opencpu in meteor (where angular could be inplemented easily).
Is it as easy as just including ocpu.seturl and jquery.min.js in meteor (as is done here), or does one need to think differently in meteor when using opencpu?
For example, there might be some conflicts between angular and meteor.
I know that is a diffuse question, but I've seen that I'm not the only one who does wonder about it.
Related:
https://groups.google.com/forum/#!topic/opencpu/rEi7lMK65GU
https://www.quora.com/Is-it-possible-to-call-the-R-server-within-a-website-made-with-Meteor-run-some-R-code-then-display-its-output
For example (thanks to http://jsfiddle.net/ramnathv/uatjd/15/):
var myApp = angular.module('myApp', ['angular-meteor']); //added 'angular-meteor'
//set CORS to call "stocks" package on public server
ocpu.seturl("//public.opencpu.org/ocpu/library/graphics/R")
myApp.factory('OpenCPU', function($http){
return {
Dist: function(dist){
var url = "http://public.opencpu.org//ocpu/library/stats/R/" + dist +
"/json"
return $http.post(url, {n: 100})
}
}
})
myApp.controller("HistCtrl", function($scope, $http, OpenCPU){
$scope.dist = 'rnorm'
$scope.dists = ['rnorm', 'runif']
$scope.color = 'blue'
$scope.colors = ['blue', 'red', 'darkmagenta']
$scope.breaks = 10
$scope.submit = function(){
var req = $("#plotdiv").rplot("hist", {
x : $scope.data,
col: $scope.color,
breaks: Math.floor($scope.breaks),
main: $scope.main
});
}
$scope.$watchCollection('[main, color, breaks, data]', function(x){
$scope.submit()
})
$scope.$watch('dist', function(newDist){
OpenCPU.Dist(newDist).success(function(result){
$scope.data = result
})
})
})
Would the above be a "correct" starting point? How should one declare dependencies in meteor (i.e. opencpu, jquery.min.js) ? New to meteor so any suggestions are highly appreciated!
Not using angular (not sure why one would need that), but here is a super basic setup in meteor:
HTML:
<head>
<title>opencpu</title>
<script src="//cdn.opencpu.org/opencpu-0.4.js"></script>
</head>
<body>
<h1>Testing OpenCPU</h1>
{{> hello}}
</body>
<template name="hello">
</template>
JS:
if (Meteor.isClient) {
Template.hello.onRendered(function() {
// ocpu.seturl("//public.opencpu.org/ocpu/library/graphics/R");
// couldn't come up with a good example for this
ocpu.seturl("//public.opencpu.org/ocpu/library/stats/R")
// this gives me a CORS error but the below still seems to work
console.log(ocpu);
var req1 = ocpu.call("rnorm", {n: 100}, function(session1){
var req2 = ocpu.call("var", {x : session1}, function(session2){
session2.getObject(function(data){
alert("Variance equals: " + data);
});
});
});
});
}
All I know about opencpu I've learned in the last 30 minutes -- little! So I don't know how to get past the CORS error. That error doesn't seem to happen when pointing at the graphics package, but for that one I couldn't think of a good example.

Unable to inject a provider into the config block

I can't get the provider injected in my config section, here my code:
<!-- they are placed in that order -->
<script src="app/components/department/DepartmentController.js"></script>
<script src="app/components/department/DepartmentProvider.js"></script>
<script src="app/components/department/DepartmentService.js"></script>
<script src="app/components/department/support/SupportController.js"></script>
<script src="app/components/department/support/SupportRouter.js"></script>
Department.js
var departmentModule = angular.module('module.department', ['ngResource']);
// departmentModule.controller('DepartmentController', function($scope) {
// nothing here
// });
DepartmentService.js:
departmentModule.factory('Department', function($http) {
return {
getAll : function(){
return $http.get('/api/departments');
},
getByName : function(name){
return $http.get('/api/department/'+name);
}
};
});
DepartmentProvider.js:
departmentModule.provider('Department', function() {
var name = 'marwen';
this.$get = function() {
return {
name: name
};
};
});
SupportRouter.js :
supportModule.config(function($stateProvider, $urlRouterProvider,$locationProvider,DepartmentProvider) {
...
I get this error: Unknown provider: DepartmentProvider
Department provider has been overridden by the Department service, you need to specify the different name for provider & service, Both can not be with a same name, The latest one will get register. As you are loading service after provider. Service gets register with in Angular App & the provider is not available inside config.
Try to change supportModule.config(function($stateProvider, $urlRouterProvider,$locationProvider,DepartmentProvider) to supportModule.config(function($stateProvider, $urlRouterProvider,$locationProvider,Department)
or change your provider name from Department to DepartmentProvider

Angular Load LinkedIn Scripts From Partial

I am using LinkedIn API and I need to load their login scripts when my user hits a certain route. However , from what I've read in stackoverflow it is not possible to just put the script elements inside a partial .
my code is straight forward :
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.0/angular.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.2.0/angular-route.js">
...
<script src="http://platform.linkedin.com/in.js">
api_key: ...
authorize: true
onLoad: onLinkedInLoad
</script>
<script type="in/Login">
Hello, <?js= firstName ?> <?js= lastName ?>.
</script>
<script src="js/linkedinFuncs.js"></script>
</div>
The 3 last scripts (the linkedin ones) only needs to be included when the user hits the 'login' route . Any thoughts?
If anyone experiences this issue :
1)Make sure you load jquery BEFORE angular
2)Run the latest angular (this issue is resolved on 1.2.9 but was unresolved for me on 1.2.0)
You could load it from the code in your relevant congtroller programmatically by using something like this
(function injectScript() {
var src = 'http://platform.linkedin.com/in.js',
script = document.createElement('script');
script.async = true;
script.src = src;
var api_key = 'YOUR_KEY_HERE';
//script.authorize = true;
script.text = 'api_key: ' + api_key + '\n' + 'authorize: true\n';
script.onload = function() {
IN.Event.on(IN, 'systemReady', function() {
loadDeferred.resolve(IN);
});
};
document.getElementsByTagName('head')[0].appendChild(script);
})();

Inject module dynamically, only if required

I'm using Require.js in combination with Angular.js.
Some controllers need huge external dependencies which others don't need, for example, FirstController requires Angular UI Codemirror. That's a extra 135 kb, at least:
require([
"angular",
"angular.ui.codemirror" // requires codemirror itself
], function(angular) {
angular.module("app", [ ..., "ui.codemirror" ]).controller("FirstController", [ ... ]);
});
I don't want to have to include the directive and the Codemirror lib everytime my page loads just to make Angular happy.
That's why I'm right now loading the controller only when the route is hit, like what's done here.
However, when I need something like
define([
"app",
"angular.ui.codemirror"
], function(app) {
// ui-codemirror directive MUST be available to the view of this controller as of now
app.lazy.controller("FirstController", [
"$scope",
function($scope) {
// ...
}
]);
});
How can I tell Angular to inject ui.codemirror module (or any other module) in the app module aswell?
I don't care if it's a hackish way to accomplish this, unless it involves modifying the code of external dependencies.
If it's useful: I'm running Angular 1.2.0.
I have been trying to mix requirejs+Angular for some time now. I published a little project in Github (angular-require-lazy) with my effort so far, since the scope is too large for inline code or fiddles. The project demonstrates the following points:
AngularJS modules are lazy loaded.
Directives can be lazy loaded too.
There is a "module" discovery and metadata mechanism (see my other pet project: require-lazy)
The application is split into bundles automatically (i.e. building with r.js works)
How is it done:
The providers (e.g. $controllerProvider, $compileProvider) are captured from a config function (technique I first saw in angularjs-requirejs-lazy-controllers).
After bootstraping, angular is replaced by our own wrapper that can handle lazy loaded modules.
The injector is captured and provided as a promise.
AMD modules can be converted to Angular modules.
This implementation satisfies your needs: it can lazy-load Angular modules (at least the ng-grid I am using), is definitely hackish :) and does not modify external libraries.
Comments/opinions are more than welcome.
(EDIT) The differentiation of this solution from others is that it does not do dynamic require() calls, thus can be built with r.js (and my require-lazy project). Other than that the ideas are more or less convergent across the various solutions.
Good luck to all!
Attention: use the solution by Nikos Paraskevopoulos, as it's more reliable (I'm using it), and has way more examples.
Okay, I have finally found out how to achieve this with a brief help with this answer.
As I said in my question, this has come to be a very hacky way. It envolves applying each function in the _invokeQueue array of the depended module in the context of the app module.
It's something like this (pay more attention in the moduleExtender function please):
define([ "angular" ], function( angular ) {
// Returns a angular module, searching for its name, if it's a string
function get( name ) {
if ( typeof name === "string" ) {
return angular.module( name );
}
return name;
};
var moduleExtender = function( sourceModule ) {
var modules = Array.prototype.slice.call( arguments );
// Take sourceModule out of the array
modules.shift();
// Parse the source module
sourceModule = get( sourceModule );
if ( !sourceModule._amdDecorated ) {
throw new Error( "Can't extend a module which hasn't been decorated." );
}
// Merge all modules into the source module
modules.forEach(function( module ) {
module = get( module );
module._invokeQueue.reverse().forEach(function( call ) {
// call is in format [ provider, function, args ]
var provider = sourceModule._lazyProviders[ call[ 0 ] ];
// Same as for example $controllerProvider.register("Ctrl", function() { ... })
provider && provider[ call[ 1 ] ].apply( provider, call[ 2 ] );
});
});
};
var moduleDecorator = function( module ) {
module = get( module );
module.extend = moduleExtender.bind( null, module );
// Add config to decorate with lazy providers
module.config([
"$compileProvider",
"$controllerProvider",
"$filterProvider",
"$provide",
function( $compileProvider, $controllerProvider, $filterProvider, $provide ) {
module._lazyProviders = {
$compileProvider: $compileProvider,
$controllerProvider: $controllerProvider,
$filterProvider: $filterProvider,
$provide: $provide
};
module.lazy = {
// ...controller, directive, etc, all functions to define something in angular are here, just like the project mentioned in the question
};
module._amdDecorated = true;
}
]);
};
// Tadaaa, all done!
return {
decorate: moduleDecorator
};
});
After this has been done, I just need, for example, to do this:
app.extend( "ui.codemirror" ); // ui.codemirror module will now be available in my application
app.controller( "FirstController", [ ..., function() { });
The key to this is that any modules your app module depends on also needs to be a lazy loading module as well. This is because the provider and instance caches that angular uses for its $injector service are private and they do not expose a method to register new modules after initialization is completed.
So the 'hacky' way to do this would be to edit each of the modules you wish to lazy load to require a lazy loading module object (In the example you linked, the module is located in the file 'appModules.js'), then edit each of the controller, directive, factory etc calls to use app.lazy.{same call} instead.
After that, you can continue to follow the sample project you've linked to by looking at how app routes are lazily loaded (the 'appRoutes.js' file shows how to do this).
Not too sure if this helps, but good luck.
There is a directive that will do this:
https://github.com/AndyGrom/loadOnDemand
example:
<div load-on-demand="'module_name'"></div>
The problem with existing lazy load techniques is that they do things which I want to do by myself.
For example, using requirejs, I would like to just call:
require(['tinymce', function() {
// here I would like to just have tinymce module loaded and working
});
However it doesn't work in that way. Why? As I understand, AngularJS just marks the module as 'to be loaded in the future', and if, for example, I will wait a bit, it will work - I will be able to use it. So in the function above I would like to call some function like loadPendingModules();
In my project I created simple provider ('lazyLoad') which does exactly this thing and nothing more, so now, if I need to have some module completely loaded, I can do the following:
myApp.controller('myController', ['$scope', 'lazyLoad', function($scope, lazyLoad) {
// ........
$scope.onMyButtonClicked = function() {
require(['tinymce', function() {
lazyLoad.loadModules();
// and here I can work with the modules as they are completely loaded
}]);
};
// ........
});
here is link to the source file (MPL license):
https://github.com/lessmarkup/less-markup/blob/master/LessMarkup/UserInterface/Scripts/Providers/lazyload.js
I am sending you sample code. It is working fine for me. So please check this:
var myapp = angular.module('myapp', ['ngRoute']);
/* Module Creation */
var app = angular.module('app', ['ngRoute']);
app.config(['$routeProvider', '$controllerProvider', function ($routeProvider, $controllerProvider) {
app.register = {
controller: $controllerProvider.register,
//directive: $compileProvider.directive,
//filter: $filterProvider.register,
//factory: $provide.factory,
//service: $provide.service
};
// so I keep a reference from when I ran my module config
function registerController(moduleName, controllerName) {
// Here I cannot get the controller function directly so I
// need to loop through the module's _invokeQueue to get it
var queue = angular.module(moduleName)._invokeQueue;
for (var i = 0; i < queue.length; i++) {
var call = queue[i];
if (call[0] == "$controllerProvider" &&
call[1] == "register" &&
call[2][0] == controllerName) {
app.register.controller(controllerName, call[2][1]);
}
}
}
var tt = {
loadScript:
function (path) {
var result = $.Deferred(),
script = document.createElement("script");
script.async = "async";
script.type = "text/javascript";
script.src = path;
script.onload = script.onreadystatechange = function (_, isAbort) {
if (!script.readyState || /loaded|complete/.test(script.readyState)) {
if (isAbort)
result.reject();
else {
result.resolve();
}
}
};
script.onerror = function () { result.reject(); };
document.querySelector(".shubham").appendChild(script);
return result.promise();
}
}
function stripScripts(s) {
var div = document.querySelector(".shubham");
div.innerHTML = s;
var scripts = div.getElementsByTagName('script');
var i = scripts.length;
while (i--) {
scripts[i].parentNode.removeChild(scripts[i]);
}
return div.innerHTML;
}
function loader(arrayName) {
return {
load: function ($q) {
stripScripts(''); // This Function Remove javascript from Local
var deferred = $q.defer(),
map = arrayName.map(function (obj) {
return tt.loadScript(obj.path)
.then(function () {
registerController(obj.module, obj.controller);
})
});
$q.all(map).then(function (r) {
deferred.resolve();
});
return deferred.promise;
}
};
};
$routeProvider
.when('/first', {
templateUrl: '/Views/foo.html',
resolve: loader([{ controller: 'FirstController', path: '/MyScripts/FirstController.js', module: 'app' },
{ controller: 'SecondController', path: '/MyScripts/SecondController.js', module: 'app' }])
})
.when('/second', {
templateUrl: '/Views/bar.html',
resolve: loader([{ controller: 'SecondController', path: '/MyScripts/SecondController.js', module: 'app' },
{ controller: 'A', path: '/MyScripts/anotherModuleController.js', module: 'myapp' }])
})
.otherwise({
redirectTo: document.location.pathname
});
}])
And in HTML Page:
<body ng-app="app">
<div class="container example">
<!--ng-controller="testController"-->
<h3>Hello</h3>
<table>
<tr>
<td>First Page </td>
<td>Second Page</td>
</tr>
</table>
<div id="ng-view" class="wrapper_inside" ng-view>
</div>
<div class="shubham">
</div>
</div>

Resources