how to call angular factory method from module setup? - javascript

I have a module App and factory i18n, what is the best way to call i18n.load
method form App (config? run? etc?)
angular
.module('App', [
'ngRoute',
'service.i18ndb'
])
.config(function ($routeProvider) {
//want to i18n.load() here somehow
$routeProvider
.when('/signin', {
templateUrl: '../views/sign-in.html',
controller: 'SigninCtrl'
})
.when('/mix', {
templateUrl: '../views/mix.html',
controller: 'MixCreateCtrl'
})
.otherwise({
redirectTo: '/signin'
});
});
angular.module('App')
.factory('service.i18ndb', function() {
return {
load: function() { console.log("Busy"); }
}
}
);

The problem you will always have if you use .run is having to deal with a page that has no i18n loaded. This means you will need to have a way to deal with your view when their is no i18n loaded. You can either hide it or the text will flash with the wrong values at first.
However, AngularJS gives you a wonderful feature to make sure it is loaded before your view is loaded: the resolver!
Here is how to do it.
var i18nResolver = function(service.i18ndb) {
return service.i18ndb.promise;
};
$routeProvider
.when('/signin' {
templateUrl: '../views/sign-in.html',
controller: 'SigninCtrl',
resolve: {
i18n: i18nResolver
}
});
You can fix this code to use the correct promise of your HTTP request or whatever service you are using.
One of the benefits of using this way is you can have a different labels for a different page for your i18n and use the i18n service to recover them no matter where you are.

You are defining your app module twice. One you create your factory, it can be injected to the controller and used there. You could try something like this:
angular.module('App', ['ngRoute','service.i18ndb'])
.factory('service.i18ndb', function() {
return {
load: function() { console.log("Busy"); }
}
})
.config(function ($routeProvider) {
//want to i18n.load() here somehow
$routeProvider
.when('/signin', {
templateUrl: '../views/sign-in.html',
controller: 'SigninCtrl'
})
.when('/mix', {
templateUrl: '../views/mix.html',
controller: 'MixCreateCtrl'
})
.otherwise({
redirectTo: '/signin'
});
})
.controller('SigninCtrl', function($scope, service.i18ndb) {
// Call your factory function here
service.i18ndb.load();
// If the function returns a value you could assign it to a scope
// variable so it can be used in your template 'sign-in.html'
$scope.your_variable = service.i18ndb.load();
});

angular
.module('App', [
'ngRoute'
])
.config(function ($routeProvider) {
//want to i18n.load() here somehow
$routeProvider
.when('/signin', {
templateUrl: '../views/sign-in.html',
controller: 'SigninCtrl'
})
.when('/mix', {
templateUrl: '../views/mix.html',
controller: 'MixCreateCtrl'
})
.otherwise({
redirectTo: '/signin'
});
})
.run(['i18ndb', function(i18ndb) {
i18ndb.load();
}])
.factory('i18ndb', function() {
return {
load : function() {console.log('test')}
};
});
);
You were requiring a module which has not been defined (as far as I can tell). The factory you were adding was on the 'App' module not the 'service.i18ndb'.
You then need to dependency inject the i18ndb factory in to the run method to call it from there (presuming that you want to call that function to bootstrap your app).

Related

AngularJS: Parameterize controller via route

I use the same controller for multiple views. I want to parameterize the controller differently depending on the route taken.
The views display basically the same angular ui grid, hence the same controller. However, in one view I want to pre-filter the grid for specific data, whereas in the other I don't.
How can I do that?
app.config(function ($routeProvider) {
$routeProvider
.when('/foo',
{
controller: 'Ctrl',
templateUrl: '/foo.html',
})
.when('/bar',
{
controller: 'Ctrl',
templateUrl: '/bar.html',
});
});
app.controller('Ctrl', ['$scope' function ($scope) { .. }]);
Think of it that way.
Both routes are the same except one has a filter and one doesn't. so in reality it's the same route with additional parameter filter='some' right so your configuration might be something like this:
app.config(function ($routeProvider) {
$routeProvider
.when('/foo/:filter?',
{
controller: 'Ctrl',
templateUrl: '/foo.html',
})
});
and in your controller you'll have $routeParams.filter question mark would be an optional parameter. Then in the Ctrl you would just look for filter parameter and use filter to render appropriately.
Btw your view can stay the same just filter your grid anyways. if filter param doesn't exist it will just return same data (unfiltered)
Hope that helps.
At the basic level, you could inspect the current route to see what template was being used and branch off that.
app.controller('Ctrl', function($route) {
if ($route.current.templateUrl === '/foo.html') {
doFoo();
} else {
doBar();
}
});
That would only work if you are using different templates for each route. If you wanted to re-use the same template, the resolve property of the route is very useful.
app.config(function($routeProvider) {
$routeProvider.when('/foo', {
controller: 'Ctrl',
templateUrl: '/foo.html'
resolve: {
whichRoute: function() { return 'foo'; }
}
});
});
app.controller('Ctrl', function(whichRoute) {
if (whichRoute === 'foo') {
doFoo();
} else {
doBar();
}
});
And even better than that, the resolve properties can accept functions that return values or promises, so you could do the pre-filtering of the data in there.
app.config(function($routeProvider) {
$routeProvide.when('/foo', {
controller: 'Ctrl',
templateUrl: '/foo.html',
resolve: {
dataToDisplay: function(YourDataService) {
return YourDataService.getSomeData();
}
}
});
});
app.controller('Ctrl', function(dataToDisplay) {
doTheThing(dataToDisplay);
});

AngularJS: Component controller not loaded when routing with ngRoute

I am an AngularJS beginner. I have the following code:
A component defined by the following js file:
angular.module('EasyDocsUBBApp')
.component('loginTag', {
templateUrl: 'login-tag/login-tag.html',
controller: function () {
alert(1);
this.login = function () {
console.log(this.username + ':' + this.password);
};
}
});
The content of my app.js file, where I also configured the routing is:
var app = angular.module('EasyDocsUBBApp', ['ngRoute']);
app.config(function ($routeProvider) {
$routeProvider
.when('/', {
templateUrl: 'login-tag/login-tag.html'
})
.when('/test', {
templateUrl: 'test.html'
})
.otherwise({
redirectTo: 'login-tag/login-tag.html'
});
});
My issue is that the controller is not loaded (the alert window does not appear). Could someone indicate me what I did wrong? (if any supplementary details on my code are needed, please tell me)
In your configuration for $routeProvider, try this:
.when('/', {
template: '<login-tag></login-tag>'
})
Remember to add your component.js to your index file.

Angular $routeProvider to handle different URLs differently

In angular, is there a method to load different views & controllers when the routes are basically the same, but the actual string in the route is different?
In terms of routing, if the top level route parameter is being already used, is there way to load different View & Controller based on the different route parameter?
Below is what I was trying:
app.config(['$routeProvider',
function($routeProvider) {
$routeProvider
.when("/", {
templateUrl: "app/components/0_home/homeView.html",
controller: "HomeController"
}) // Home
.when("/about", {
templateUrl: "app/components/1_about/aboutView.html",
controller: "AboutController"
}) // About
/*(...Bunch of other .whens)*/
//Project
.when("/project/:projectId", {
templateUrl: "app/components_project/0_home/homeView.html",
controller: "ProjectHomeController"
})
.when("/project/:projectId/HOME", {
templateUrl: "app/components_project/0_home/homeView.html",
controller: "ProjectHomeController"
})
.when("/project/:projectId/FLOORPLAN", {
templateUrl: "app/components_project/1_floorplans/floorplanView.html",
controller: "FloorplanController"
}) // Floorplan
.when("/404", {
templateUrl: "app/components/404.html"
}) // else 404
.otherwise({
redirectTo: '/404'
});
}
]);
I wanted to load
app/components_project/0_home/homeView.html
when routeProvider is
/project/:projectId/HOME
and load
app/components_project/1_floorplans/floorplanView.html
when routeProvider is
/project/:projectId/FLOORPLAN
Or is there any better way to handle this kind of situation?

Extending a service provider (provider)

I'm trying to extend a service provider; more specifically $routeProvider from the ngRoute module
my extended provider looks like this:
angular
.module('myapp')
.provider('customRoute', customRoute)
function customRoute($routeProvider) {
var extendedProvider = angular.extend({}, $routeProvider, {
// Customization here
});
// These will print almost identical objects
console.log(extendedProvider);
console.log($routeProvider);
this.$get = function() {
return extendedProvider;
}
}
The config of the routes looks something like this:
angular
.module('myapp')
.config(Routes);
function Routes(customRouteProvider, $routeProvider) {
/* This will print an object that looks the same as
the ones printed in the provider definition */
console.log($routeProvider);
/* This object does not look like the $routeProvider any more :( */
console.log(customRouteProvider);
customRouteProvider
.when('/', {
templateUrl: 'path/to/some/template.html',
controller: 'SomeController',
})
.otherwise({
redirectTo: '/'
});
}
I've read this thread:
how can i extend a service
But they only talk about extending the "factory"-service
Can someone explain what is happening here? Help is much appreciated.
In order to extend $routeProvider your customRoute function must return extended provider object:
function customRoute($routeProvider) {
var extendedProvider = angular.extend({}, $routeProvider, {
// Customization here
mergeRoutes: function() {}
});
return extendedProvider;
}
After that you could for example you new custom method customRouteProvider.mergeRoutes:
customRouteProvider
.when('/', {
templateUrl: 'path/to/some/template.html',
controller: 'SomeController',
})
.otherwise({
redirectTo: '/'
})
.mergeRoutes({ ... });
Demo to play: http://plnkr.co/edit/mht94RFLScz2jHCwPcai?p=preview
For your purposes you don't need to mess with this.$get, you just need to add some new methods to $routeProvider. this.$get returns a service object instance/constructor for corresponding provider service ($route in case of $routeProvider).

How can you manually inject route resolve data inside a controller?

I have 2 routes that share a controller, one needs data resolved prior to the view loading, and the other does not need the resolved data.
Routing segment example:
...
when('/users', {
controller: 'UsersCtrl',
templateUrl: '/partials/users/view.html',
resolve: {
resolvedData : ['Accounts', function(Accounts) {
return Accounts.get();
}]
}
}).
when('/users/add', {
controller: 'UsersCtrl',
templateUrl: '/partials/users/add.html'
})
...
Controller example:
app.controller('UsersCtrl', ['$scope', 'Helper', 'resolvedData',
function($scope, Helper, resolvedData) {
// this works for the first route, but fails for the second route with
// unknown "resolvedDataProvider"
console.log(resolvedData);
}]);
Is there any way I can get the resolvedData in the controller without explicitly using the resolve name as a dependency? So a check can be performed?
Using the $injector does not work. I would like to do something similar to:
if ($injector.has('resolveData')) {
var resolveData = $injector.get('resolveData');
}
However this does not work even for the route that has the resolveData set ('/users'):
app.controller('UsersCtrl', ['$scope', 'Helper', '$injector',
function($scope, Helper, $injector) {
// this does not work -> fails with the unknown "resolvedDataProvider" as well
$injector.get('resolvedData');
}]);
Can this be done in angularjs? Or should I just create a new controller?
Thank you.
Looks like I figured out another way to go. The resolved data is part of the $route. So you can access it using:
app.controller('UsersCtrl', ['$scope', '$route', 'Helper',
function($scope, $route, Helper) {
if ($route.current.locals.resolvedData) {
var resolvedData = $route.current.locals.resolvedData;
}
}]);
If the other route doesn't need it, just inject undefined on that route:
router:
when('/users', {
controller: 'UsersCtrl',
templateUrl: '/partials/users/view.html',
resolve: {
resolvedData : ['Accounts', function(Accounts) {
return Accounts.get();
}]
}
}).
when('/users/add', {
controller: 'UsersCtrl',
templateUrl: '/partials/users/add.html',
resolve: {
resolvedData: function() {
return undefined;
}
}
})
controller:
app.controller('UsersCtrl', ['$scope', 'Helper', 'resolvedData',
function($scope, Helper, resolvedData) {
if(resolvedData){
//set some scope stuff for it
} else {
//do what you do when there is no resolvedData
}
}]);

Categories