Want to compare from one module with another module - angularjs

angular.module('MyApp')
//var appVersion = '20171901'
.constant('API_URL', '/xyz/');
.config(["checkAppVersion", function(checkAppVersion) {
checkAppVersion.appVersion='20171203';
}])
This is my app.config file ,Here i want to set app version right now am keeping it manually ,
angular.module(MyApp.user).
controller('appVersionCtrl',function(checkAppVersion){
//ctrler
if(user.appversion === checkAppVersion){
//do something
}
}
Now i want to check version of user and version i set in myApp is equal or not
is I did it correctly if not whats the way?

Declare your app version in constants
angular.module('MyApp')
//var appVersion = '20171901'
.constant('userconstants', {
"API_URL": "/xyz/",
"appVersion": "1.0",
});
and in your second module include the first module
angular.module('MyApp.user', [
'ionic',
'MyApp',
])
And then In your controller, you can directly use the constant to compare
.controller('appVersionCtrl', function (userconstants) {
if(appversion === userconstants.appVersion){
//do something
}
}

Related

How to create and use separate file for each language in angular-translate with requirejs-angularAMD?

Using angualr-translate with requirejs. Want to create separate files for each language (contains translate keys), for the time it is all in app.js.
Example- app.js
define(['angularAMD', 'ngRoute','pascalprecht.translate'], function (angularAMD) {
var app = angular.module('app', ['ngRoute','pascalprecht.translate']);
app.config(['$routeProvider','$translateProvider', function($routeProvider,$translateProvider){
/* *************** routes *************** */
//...........
/* *************** routes *************** */
/* angular translate */
$translateProvider.translations('en', {
add_user: 'Add User',
first_name:'First Name',
last_name:'Last Name',
//.....
//IMPORTANT: more than 1000 translate keys...
//.....
});
$translateProvider.translations('de', {
add_user: 'Benutzer hinzufügen',
first_name:'Vorname',
last_name:'Last Name',
//.....
//IMPORTANT: more than 1000 translate keys...
//.....
});
// Bootstrap Angular when DOM is ready
return angularAMD.bootstrap(app);
});
For case you want to use js instead of JSON.
var app = angular.module('myModule', []);
app.config(function ($translateProvider) {
$translateProvider.useLoader('customLoader', {
// if you have some custom properties, go for it!
});
});
app.factory('customLoader', function ($http, $q) {
// return loaderFn
return function (options) {
var deferred = $q.defer();
// do something with $http, $q and key to load localization files
// or do something to load file with requireJS
require(['en-US'], function(translation){
var data = translation;
}
return deferred.resolve(data);
// or
return deferred.reject(options.key);
};
});
this is an modified example in the preference link of asynchronus-loading in the end of the answer (section Using custom loader service)
OLD ANSWER
angular-translate supports on-demand load for translation files. You don't need to use requireJS in this case.
Currenly this is my code in app.config()
$translateProvider.useUrlLoader('/translate');
$translateProvider.preferredLanguage('en');
$translateProvider.fallbackLanguage('en');
all you need to do is setup url like below
{your_host}/something-translate?lang={language_key}
In my case, the server real url is like.
localhost/translate?lang=en
localhost/translate?lang=fr
localhost/translate?lang=es
...
Then in controller:
$scope.translate = function (langKey){
$translate.use(langKey);
}
Preference link:
https://github.com/angular-translate/angular-translate/wiki/Asynchronous-loading#registering-asynchronous-loaders
https://github.com/angular-translate/angular-translate/wiki/Extensions

Using Express to render an .ejs template for AngularJS and use the data inside AngularJS $scope

I hope I can explain myself with this first question I post on Stack Overflow.
I am building a small test application with the MEAN stack.
The application receives variable data from Mongoose based on an Express Route I have created.
For example the url is: localhost:3000/cities/test/Paris
Based on the name of the city the response gives me the name of the city and a description. I Know how to get this data inside the .ejs template
But thats not what I want. I want to use this data inside an ngRepeat.
Maybe this is not the right way but maybe you can help me figure this out.
The reason I want to do this is because I don't want a single page application but an Angular template that can be used over and over for each city and only uses the data that gets back from the mongoose find() results and not the whole cities array.
app.js :
var cityRoutes = require('./routes/cities');
app.use('/cities', cityRoutes);
app.set('views', './views'); // specify the views directory
app.set('view engine', 'ejs'); // register the template engine
./routes/cities/cities.js :
var express = require('express');
var citiesList = require('../server/controllers/cities-controller');
var bodyParser = require('body-parser');
var urlencode = bodyParser.urlencoded({ extended: false });
var router = express.Router();
// because this file is a fallback for the route /cities inside app.js
// the route will become localhost:3000/cities/test/:name
// not to be confused by its name in this file.
router.route('/test/:name')
.get(citiesList.viewTest)
module.exports = router;
../server/controllers/cities-controller.js :
var City = require('../models/cities');
module.exports.viewTest = function(request, responce){
City.find({ stad: request.params.name }, function(err, results){
if (err) return console.error(err);
if (!results.length) {
responce.json( "404" );
} else {
responce.render('angular.ejs', { messages:results });
// through this point everything works fine
// the angular.ejs template gets rendered correctly
// Now my problem is how tho get the results from the
// response.render inside the Angular directive
// so I can use the data in a $scope
}
});
};
../models/cities.js
var mongoose = require('mongoose');
module.exports = mongoose.model('City', {
stad: { type: String, required: true },
omschrijving: String
});
AngularJS directive :
// This is where I would like to use the messages result data
// so I can create a $scope that handles data that can be different
// for each url
// so basically I am using this directive as a template
app.directive('bestelFormulier', function () {
return {
restrict: 'E',
templateUrl: '/partials/bestel-formulier.html',
controller: ['$scope', '$http', '$resource', '$cookieStore',
function($scope, $http, $resource, $cookieStore){
// at this point it would be nice that the $scope gets the
// url based results. But I don't now how to do that..
// at this point the var "Cities" gets the REST API with
// all the cities...
var Cities = $resource('/cities');
// get cities from mongodb
Cities.query(function(results){
$scope.cities = results;
//console.log($scope.products);
});
$scope.cities = {};
}],
controllerAs: 'productsCtrl'
}
});
The database is stored like this :
[
{
stad: 'Paris',
omschrijving: 'description Paris',
},
{
stad: 'Amsterdam',
omschrijving: 'description Amsterdam',
}
]
I hope these files included helps explaining my issue.
Thanks in advance for helping me out
I figured out a way to do it...
The following changes to my code fixed my issue.
in app.js
var cityRoutes = require('./routes/cities');
app.use('/', cityRoutes);
// removed the name cities
./routes/cities/cities.js :
router.route('/cities/test/:name')
.get(citiesList.viewTest)
// added this route to use as an API
router.route('/api/cities/test/:name')
.get(citiesList.viewStad)
../server/controllers/cities-controller.js :
// added this callback so that a request to this url
// only responses with the data I need
module.exports.viewStad = function(request, responce){
City.find({ stad: request.params.name }, function(err, results){
if (err) return console.error(err);
if (!results.length) {
responce.json( "404" );
} else {
responce.json( results );
}
});
};
in my AngularJS app I added the $locationDirective and changed the following in my Angular directive to :
var url = $location.url();
var Cities = $resource('/api' + url);
// now when my .ejs template gets loaded the Angular part looks at
// the current url puts /api in front of it and uses it to get the
// correct resource
That is the way how I can use it in my $scope and use al the lovely Angular functionality :-)
Hope I can help other people with this... Eventually it was a simple solution and maybe there are people out there knowing beter ways to do it. For me it works now.

Accesing javascript variable in angularjs

I am trying to accessing javascript variable and then change it in controller and then use it in route.. but it is showing the same old one.
var userEditid = 0;
app.controller("cn_newuser", function ($scope,$window) {
editUser = function (this_) {
$window.userEditid = this_.firstElementChild.value;
alert(userEditid);
//window.location.path("#/edit_user");
//$window.location.href = "#/edit_user";
}
route
.when("/edit_user", {
templateUrl: "/master/edituser/" + userEditid //userEditid should be 3 or some thing else but is showing 0
})
in abobe route userEditid should be 3 or some thing else but is showing 0
This is because the .when() is evaluated on app instantiation, when this global var (which is really not a great idea anyways) is set to 0, rather than when your controller is run. If you are trying to say, "load the template, but the template name should vary based on a particular variable," then the way you are doing it isn't going to work.
I would do 2 things here:
Save your variable in a service, so you don't play with global vars
Have a master template, which uses an ng-include, which has the template determined by that var
Variable in a service:
app.controller("cn_newuser", function ($scope,UserIdService) {
$scope.editUser = function (this_) {
UserIdService.userEditid = this_.firstElementChild.value;
$location.path('/edit_user');
}
});
also note that I changed it to use $location.path()
Master template:
.when("/edit_user", {
templateUrl: "/master/edituser.html", controller: 'EditUser'
});
EditUser controller:
app.controller("EditUser", function ($scope,UserIdService) {
$scope.userTemplate = '/master/edituser/'+UserIdService.userEditId;
});
And then edituser.html would be:
<div ng-include="userTemplate"></div>
Of course, I would ask why you would want a separate template per user, rather than a single template that is dynamically modified by Angular, but that is not what you asked.
EDITED:
Service would be something like
app.factory('UserIdService',function() {
return {
userEditId: null
}
});
As simple as that.

AngularJs - get list of all registered modules

Can I get a list of all registered modules at run time?
For example:
// Some code somewhere in some .js file
var module1 = angular.module('module1', []);
// Some code in some other .js file
var module2 = angular.module('module2', []);
// Main .js file
var arrayWithNamesOfAllRegisteredModules = .....
// (result would be: ['module1', 'module2'])
Angular does not provide a way to retrieve the list of registered modules (at least I was not able to find a way in source code). You can however decorate angular.module method to store names in array. Something like this:
(function(orig) {
angular.modules = [];
angular.module = function() {
if (arguments.length > 1) {
angular.modules.push(arguments[0]);
}
return orig.apply(null, arguments);
}
})(angular.module);
Now you can check angular.modules array.
Demo: http://plnkr.co/edit/bNUP39cbFqNLbXyRqMex?p=preview
You can simply do :
console.log(angular.module('ModuleYouWantToInspect').requires);
It should return of an array of strings (dependencies). You can do the same for the output.
Given an angular.element, the $injector.modules array contains the list of registered modules.
e.g.
angular.element(document.body).injector().modules
If you're debugging, I discovered you can get the list by:
Find or add code to invoke run() from any module with any body, say:
angular.module('myModule')
.run(function() {})
Put a breakpoint on the .run, and step into angular.run(). There's an object called "modules" in scope that has all the modules as properties, by name.
This may work with other module methods too, or be accessible from code; I haven't tried very hard to understand the larger picture.
Improving solution
(function(angular) {
var orig = angular.module;
angular.modules = [];
angular.modules.select = function(query) {
var cache = [], reg = new RegExp(query || '.*');
for(var i=0,l=this.length;i< l;i++){
var item = this[i];
if(reg.test(item)){
cache.push(item)
}
}
return cache;
}
angular.module = function() {
var args = Array.prototype.slice.call(arguments);
if (arguments.length > 1) {
angular.modules.push(arguments[0]);
}
return orig.apply(null, args);
}
})(angular);
Now you can select modules:
angular.modules.select('app.modules.*')
Creating modules tree:
var app = angular.module('app.module.users', ['ui.router'...]);
var app = angular.module('app.module.users.edit', ['app.modules.users']);
Your main module app (concat submodules)
angular.module('app', ['ui.bootstrap', 'app.services', 'app.config']
.concat(angular.modules.select('app.module.*')));
in addition to #dfsq answer you can get list of modules with it dependencies
var AngularModules = (function (angular) {
function AngularModules() {
extendAngularModule();
angular.element(document).ready(function () {
getModulesDependencies();
});
}
var extendAngularModule = function () {
var orig = angular.module;
angular.modules = [];
angular.module = function () {
var args = Array.prototype.slice.call(arguments);
var modules = [];
if (arguments.length > 1) {
modules.push(arguments[0]);
}
for (var i = 0; i < modules.length; i++) {
angular.modules.push({
'module': modules[i]
});
}
return orig.apply(null, args);
};
};
var getModulesDependencies = function () {
for (var i = 0; i < angular.modules.length; i++) {
var module = angular.module(angular.modules[i].module);
angular.modules[i].dependencies = module && module.hasOwnProperty('requires') ? module.requires : [];
}
};
return AngularModules;
})(angular);
Usage:
var modules = new AngularModules();
There is a similar question with better answers here https://stackoverflow.com/a/19412176/132610, a summary of what they proposed is:
var app = angular.module('app', []);
# app.service(/**your injections*/) etc
# to access to the list of services + injections
app._invokeQueue #has following form:
[
[
'$provide',
'service',
Arguments[
'serviceName',
[
'$dependency1',
'$dependency2',
function(){}
],
]
]
]
This involves poking at implementation details that may change over time, but you can try this.
Load the page fully.
Set a breakpoint inside angular.module().
Call angular.module() from the console.
When you hit the breakpoint execute print out the modules dictionary console.dir(modules) or if you want to copy it into another editor window.prompt('', JSON.stringify(modules))
This works because behind the scenes angular builds a dictionary of the loaded modules called modules. You also want to wait until it's finished loading all the modules so they're in the dictionary.

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