Otherwise on StateProvider - angularjs

Using angular-ui-router, How can I use the otherwise method on $stateProvider or how can I use it at all ?

You can't use only $stateProvider.
You need to inject $urlRouterProvider and create a code similar to:
$urlRouterProvider.otherwise('/otherwise');
The /otherwise url must be defined on a state as usual:
$stateProvider
.state("otherwise", { url : '/otherwise'...})
See this link where ksperling explains

You can with $stateProvider using the catch all syntax ("*path"). You just need to add a state config at the bottom of your list like the following one:
$stateProvider.state("otherwise", {
url: "*path",
templateUrl: "views/error-not-found.html"
});
All the options are explained in https://github.com/angular-ui/ui-router/wiki/URL-Routing#regex-parameters.
The nice thing of this option, as opposed to $urlRouterProvider.otherwise(...), is that you 're not forced to a location change.

You can also manually inject $state into the otherwise function, which you can then navigate to a non-url state. This has the benefit of the browser not changing the addressbar, which is helpful for handling going back to a previous page.
$urlRouterProvider.otherwise(function ($injector, $location) {
var $state = $injector.get('$state');
$state.go('defaultLayout.error', {
title: "Page not found",
message: 'Could not find a state associated with url "'+$location.$$url+'"'
});
});

I just want to chime in on the great answers that are already provided. The latest version of #uirouter/angularjs marked the class UrlRouterProvider as deprecated. They now recommend using UrlService instead. You can achieve the same result with the following modification:
$urlService.rules.otherwise('/defaultState');
Additional methods: https://ui-router.github.io/ng1/docs/1.0.16/interfaces/url.urlrulesapi.html

Ok, the silly moment when you realize that the question you asked is already answered in the first lines of the sample code! Just take a look at the sample code.
angular.module('sample', ['ui.compat'])
.config(
[ '$stateProvider', '$routeProvider', '$urlRouterProvider',
function ($stateProvider, $routeProvider, $urlRouterProvider) {
$urlRouterProvider
.when('/c?id', '/contacts/:id')
.otherwise('/'); // <-- This is what I was looking for !
....
Take a look here.

The accepted answer references angular-route asks about ui-router. The accepted answer uses the "monolithic" $routeProvider, which requires the ngRoute module (whereas ui-router needs the ui.router module)
The highest-rated answer uses $stateProvider instead, and says something like .state("otherwise", { url : '/otherwise'... }),
but I can't find any mention of "otherwise" in the documentation it links. However, I see that $stateProvider is mentioned in this answer where it says:
You can't use only $stateProvider. You need to inject $urlRouterProvider
That's where my answer might help you. For me, it was sufficient to use $urlRouterProvider just like this:
my_module
.config([
, '$urlRouterProvider'
, function(
, $urlRouterProvider){
//When the url is empty; i.e. what I consider to be "the default"
//Then send the user to whatever state is served at the URL '/starting'
//(It could say '/default' or any other path you want)
$urlRouterProvider
.when('', '/starting');
//...
}]);
My suggestion is consistent with the ui-router documentation, (this specific revision), where it includes a similar use of the .when(...) method (the first call to the function):
app.config(function($urlRouterProvider){
// when there is an empty route, redirect to /index
$urlRouterProvider.when('', '/index');
// You can also use regex for the match parameter
$urlRouterProvider.when(/aspx/i, '/index');
})

Related

How to use angularjs config block?

I am new to angularJS and trying to learn it. I came across config function
where I see two different arguments as in below example.
Example 1
dashboardApp.config(function($stateProvider, $urlRouterProvider) {
//$urlRouterProvider.when('', '/add');
$stateProvider.state('add',
{
url:'/add?month&year',
templateUrl: 'partial/add.html',
controller: 'AddListController'
})
});
Example 2
gm.config(['$routeProvider', 'Path', function($routeProvider, Path) {
$routeProvider.when('/login', {
templateUrl: Path.view('application/authentication/login.html'),
controller: 'authController'
});
}]);
In the first example, config has a function parameter. And in second example config has array parameter.
Can someone please explain to me what is the difference between these two approaches and when to use which?
There are two differences here. The first example is providing configuration for Angular UI Router, whereas the second is using ngRoute.
The difference in syntax that you noted is the difference between having code that will not withstand minification (first example) and code that will withstand minification.
+1 to the previous answer pointing out $stateProvider is angular ui-router syntax. I would also point out that declaring $routeProvider has different syntax than other angular items like services and controllers.
You should use ui-route provider as it is better than ngRoute,
ui-router allows you to code your templates in a nested form

Angular.js create routes from json file

I have an angular.js application with a CMS(on S3). I would like to be able to create an entire page including the route from the CMS without having to push new code and redeploy the application. Is there some way to do this?
From what I can tell the $routeProvider is initialized in the .config block which only allows providers to be injected. Also from what I can tell I cannot use services in the .config block which basically eliminates the possibility to reference a get request in order to generate the routes from an S3 file.
I am new-ish to angular.js but I feel like I am overlooking something. If anyone can point me in the right direction I would be really grateful! Thanks in advance!
I am not sure if there is a more "Angular" way to solve this but here is what I did.
1)Rather than store the values as .json, I simply created a .js file where I set a variable equal to the route data.
2) I used a script tag in the layout of my Angular.js application that imports the .js file that I stored on S3.
3) In the config block I created the states required like so:
#newco.config(['$provide', '$locationProvider', '$httpProvider', '$stateProvider', '$urlRouterProvider',
($provide, $locationProvider, $httpProvider, $stateProvider, $urlRouterProvider) ->
$locationProvider.html5Mode(false);
$locationProvider.hashPrefix('!');
$urlRouterProvider.otherwise('/404')
_.each routes.routes, (route) ->
$stateProvider
.state(route, {
url: if route == '/' then route else "/" + route,
templateUrl: '/pages/home/new_index',
controller: 'NewHomeController',
resolve:{
pageData: (cmsService) ->
cmsService.pageData route
basePlan: -> 'default'
customerCategoryId: -> 'domestic'
}
})
$stateProvider
.state('/404', {
templateUrl: '404.html'
})
])
If there is a better way to do this I would certainly be interested in hearing it because I almost feel like my solution is 'hackey' but I simply can't find a more appropriate solution because the routes are initialized in during the config block which forbids the use of services.
If someone has a better idea or a reason why my solution is not ideal I would love to hear it.

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§

How to set in angularjs templateUrl to location.pathname in otherwise clause

I'm new to angularjs and want to integrate it in a cakephp app. For some pages I don't have a controller since no javascript is exectuted there or because I still have to create them. I however don't want to list them all in the routes. For this reason i set it like the following:
angular.module('desktop', []).
config(['$routeProvider', '$locationProvider', function($routeProvider, $locationProvider) {
$locationProvider.html5Mode(true);
$routeProvider
.when('/', {templateUrl: 'pages/index', controller: IndexController})
.when('/clubs', {templateUrl: 'partials/clubs.html',controller: ClubListController})
.otherwise({templateUrl: location.pathname});
}]);
This is however not working. When I go to /help, nothing happens. What am i doing wrong?
From my comments:
As far as I know it there is currently no way to do this with just routes. Routes are made to be static, they are defined as the app loads and do not update dynamically as time goes by. So using location.pathname() (or directly checking window.location) won't work since the route be set to whatever the value is when the app starts, and then never change again. It won't update when you load a new path unless you do a full browser reload (this is btw possible, but a hacky sollution).
But people have been working around it using includes, which might work for you depending on what you are after. See this question and the accepted answer for an example of how this works.
AngularJS - How to use $routeParams in generating the templateUrl?

Resources