Capturing the route change in AngularJS when no route matches - angularjs

In AngularJS, is there a way to intercept a route change that is not defined in the routeProvider so the route can be looked up in the database and, if a valid match in the database, the new route can be added to the routeProvider?
I've read it is possible to add, dynamically, a route, but I need to do it when the current route has no match.

I would have used the otherwise method of $routeProvider to load a predefined page (controller) to handle undefined routes.
otherwise({
templateUrl: 'addRoute.html',
});
And then, into this controller, get the current route requested using $location ($location.url()).
Add this route dynamically if needed :
$route.routes['/new'] = {templateUrl: 'new.html'};
Finally, redirect to this route using :
$location.path('/new');
Obviously, for this to work you will need to inject $route and $location as dependency to your controller.

Assuming you can do it in controller, you can capture this event as following:
$rootScope.$on("$routeChangeSuccess", function (event, next, current) {
if(!angular.isDefined($route.current.$$route))
addDynamicRoute('using techniques mentioned above');
else
handleOtherStuff();
});

Related

Populate Scope Values from URL on Initial Load

I am new to Angular so bear with me.
I have a controller that handles the search functionality within a page.
As a user changes the search the url changes to reflect the user interaction. Then there are $http.post calls to an API to retrieve those values within the URL. A repeater in a separate controller is updated appropriately.
This works great and the scope changes correctly.
But how do I handle initial load?
If a user clicks a saved search.
Example:
http://blah/blah/blah/Search/Status-1%7CBeds-3
I would want the search fields and the scope to be set appropriately but then the same functionality should continue.
What is the best way of doing this?
If code is needed then ask, but this is more of a which direction to go question then a fix my code question.
You probably want AngularJS routing and the $routeParams object.
If that is not adequate, you can use the $location service to extract information from the URL and write it to the $scope in your controller constructor function.
If you use ui-router you can define the search string as a parameter that can be used when deep linking
app.config(['$stateProvider', '$urlRouterProvider', function($stateProvider, $urlRouterProvider) {
$stateProvider
.state('home', {
url:'/home',
templateUrl: 'templates/home.html',
controller: 'HomeController'
})
.state('search', {
url: '/search/:searchtoken',
templateUrl: 'templates/search.html',
controller: 'SearchController'
});
http://www.funnyant.com/angularjs-ui-router/
One solution is to populate the search variable with the url params. Something like:
if params
$scope.searchInputVal = params
$scope.doPostRequest()
(sorry for the coffee script syntax)
and just ensure whatever function you have to update these search parameters is firing onChange() or onClick() whichever you're using to fire the post request to begin with.

Unable to route non existing paths in Angularjs

I am unable to route the path code/:code in my website. I receive the following error:
Firefox can't find the file at /C:/Code/dola/mobileweb/app/code/123
default.htm is located in the app folder.
I am using the mobileangularui framework. I have the following routes declared (among others):
app.config(function ($routeProvider) {
$routeProvider.when('/', { templateUrl: 'codeview.htm', reloadOnSearch: false });
$routeProvider.when('/code/:code', { templateUrl: 'codeview.htm', reloadOnSearch: false });
});
Everything works fine, except when I try e.g. code/12345.
This route is intended for a call from outside, e.g. www.mywebsite.com/code/12345.
I see two issues. First is re-declaring the $routeProvider unnecessarily. The second is you don't have an "otherwise" clause to catch everything you aren't already.
Also, not an error, but good practice to follow; you are missing a controller and controllerAs explicit directive for each entry. Try this:
app.config(function ($routeProvider) {
$routeProvider
.when('/', {
templateUrl: 'codeview.htm'
, controller: 'HomeController'
, controllerAs: 'vm'
, reloadOnSearch: false
})
.otherwise({
redirectTo: '/'
})
});
This was based on the assumption that '/code/:code' is not its own page. The option is easy to add/change if this is not the case, following the above model.
Hope this helps.
-C§
-edit-
It looks as though the best way to do this (as with what I've done in my current project for such needs) is to store the code into a global (model) variable and call the redirect using $location.path('/');. Something like the below would be part of the click-function:
DataService.code = vm.code; //the code value selected
$location.path('/');
And the resulting page would have as part of its initialization routine:
vm.code = DataService.code; //retrieves the code from memory
//and uses it to populate the page appropriately
I'm unfamiliar with how to specify a URL and have it read what page it should populate based on the trailer, aside from using PHP to catch the URL extension with the index and a $_GET redirection process. I know this can be achieved using AJAX or a Jquery catch, but I'm still somewhat new to JavaScript as a whole and not sure what the process would look like.
Alternatively, you could designate a page for each possible code (ex: 12345.html || 12345.php).
Hope this also helps.
-C§

Where is the first place I can call a service in angular ui-router?

I have an Angular app and I am using ui-router.
I need to call my service at the beginning of my App before anything else runs.
Is there a way I can call a service inside of my app.js file without using app.run? Or is there a better solution other than in my app.js file?
Take a look at the resolve functionality of ui-router https://github.com/angular-ui/ui-router/wiki/Quick-Reference. You just add another field to your state called 'resolve' and then can inject the service there. By using a resolve, this route will not execute until this resolve is completed.
I have something similar in an application where I created an abstract state for others to inherit and therefore, none of the states are registered until that initial resolve function is completed.
Ex.
$stateProvider.state('someState', {
template: 'someTemplate.html',
controller: 'someController',
resolve: {
authenticate: function(AuthSrv){
//Do stuff with AuthSrv in here
}
}
})

Duplicate controller when using angularjs

I'm usnig AngularJs 1.2.25. I have a route config:
$routeProvider.when(
'/config-root',
{
templateUrl: configRootTemplate,
controller: "ClientConfig",
}
).when(
'/config-action/:action/:_id',
{
templateUrl: configActionTemplate,
controller: "ClientConfigAction",
}
).otherwise({redirectTo: '/'});
In the ClientCOnfig controller, I have a $scope.listConfig variable binding with template for creating, updating list of config.
Everything ok when the first time I visit "config-root" route, I can generate, update... the list.
But when the second time or so far, $scope.listConfig change properly when generate list, update... but the template does not change.
I think when I visit that route again, a new instance of $scope created and does not binding with the template.
How can I fix it?
You can use rootScope to preserve the value for the next time.
change that $scope to $rootScope and access that when ever its required.
If you don't want to pollute the $rootScope you can just store the values in a localStorage as a string and fetch it when ever its required.
// To store the value
localStorage['config'] = JSON.stringify(someObj)
// To fetch the value
var myConfigObj = JSON.parse(localStorage['config'])

$routeParams not available during controller initialization

I'm trying to figure out AngularJS and routing. Can someone take a look at this http://jsfiddle.net/spoon16/p9BBr/
Help me understand why $routeParams.i is undefined during initialization. What is the appropriate way to use $routeParams in my controllers?
Basically $routeParams isn't available until the route service has changed the route, meaning you should only inject the service in controllers associated with a specific route (the controller property for the route).
If you in some other controller needs to know current route etc. you should listen to the various events the route service broadcasts, e.g.
$scope.$on('$routeChangeSuccess', function (ev, current, previous) {
// ...
});
Updated fiddle.

Resources