ui-router: Default value for param not shown in URL - angularjs

I have a state that is the entry point for my application. However, the entry page requires a date parameter in order to show a list. It is configured to use the current date if no date was provided in the URL.
Technically, everything works. The default value is passed to the controller and the controller is able to use it to load some data, but it won't show the date in the URL.
This is the state configuration:
$stateProvider.state('openJobs', {
controller: 'openJobsCtrl as openJobs',
params: {
shippingDate: {
value: getFormattedCurrentDate(),
squash: false
}
},
templateUrl: 'openJobs.html',
url: '/openJobs/:shippingDate'
});
I have created a working plunkr to demonstrate the behaviour (run in new window to see URL changes). The default value will show in the URL if I create an ui-sref link to openJobs. However, if someone were to open the page directly by entering http://host.com/openJobs/ the default value will be used in the background, but not shown in the URL.
How can I achieve that, no matter how the state was opened, the default value will show in the URL?

You can redirect the incoming path using urlRouterProvider with default date appended to it. urlRouterProvider will update the browser location.
$urlRouterProvider.when("/openJobs/", function() {
return "/openJobs/" + getFormattedCurrentDate();
});
If a state is matched against state name (through ui-sref or $state.go()), browser location will be updated with url path.
Whereas, if a state is matched against url path, the browser location will not be updated because it already matched the url. That's why you need to use $urlRouterProvider in your case to append the date.

Related

How to update only browser url, not the state in AngularJs

Lets say, there is application, that can be run for different units, with different names. Before, when user select another unit, we just reinstating controller, and load new data for new unit, this changes was not reflected on url. But, now we need to add unit name to the url.
For example we have following state:
$stateProvider.state('management', {
url: '/management',
templateUrl: 'features/management/templates/management.html'
});
And in browser we can see:
http://localhost:84/#/management
Now, when we go to that state, I need browser to show something like this:
http://localhost:84/#/unitName/management
For example we have unit1, unit2, unit3, and when user switch between them, url will be changed to
http://localhost:84/#/unit1/management,
http://localhost:84/#/unit2/management,
http://localhost:84/#/unit3/management
and so on.
I can get unitName from service, for example unitService.js that will return me a unit name as a string. But I have no idea how to add this string to url in browser. This unit name should be added to all routes, but without changing them.
Can I make first function, that will add unit name to browser url after all data was loaded, and second function, that will remove that string when angular starts to searching for state by url, so instead of unit1/management it will look for /management state?
Is it possible? Thank you in advance.
You can use notify: false.
Route declaration
$stateProvider.state('management', {
url: '/:unit/management',
templateUrl: 'features/management/templates/management.html'
});
State go example
$state.go('management', {unit: 'unit1'}, {notify: false})

Angular UI router 0.2.18 param on root url

I have an issue where I want to have a parameter on the route url e.g
$stateProvider.state('/someRoute', {
url: '/:path',
.....
});
$stateProvider.state('/contact', {
url: '/contact',
.....
});
But if I do that then other pages get misinterpreted as being part of this. for example /contact url thinks that "contact" is the param and not the page.
Is there a way around this or do I need to have a sub-page e.g /something/:path?
The issue is that currently due to the order of the states, your first state will capture all urls as it's expecting some parameter.
/contact satisfies the /:path criteria.
Either move the /:path as the last state. or create a /something/:path

Disable URL change with UI-Router in Angular?

Is it possible to configure ui-router in an Angular 1.5 application to completely ignore the address bar?
Desired behaviour is something like this:
Navigating between states via UI does not change the URL
Changing the URL does not cause navigation between states, only UI or programmatic actions do (clicking the buttons, etc.)
Hitting F5 restarts the application from "default" controller
Original URL (especially query parameters) must still be accessible
UPDATE: I am creating an application with a very specific use case, not a website. Ordinary web browsing practices do not apply here. Please accept the requirements as they are, even if it may seem to contradict common sense.
Agreed that the stated approach is not good if we consider classic web app.
I tried to create a sample application with your requirement in mind.
Here is how my router configuration(router.config.js) file looks like in my fruits app:
.state('start', {
url: '/',
templateUrl: '../app/start/start.html',
controller: 'startCtrl as vm',
})
.state('fruits', {
templateUrl: '../app/fruits/fruitshtml',
controller: 'fruitsCtrl as vm',
})
.state('fruits.details', {
params: {
fruitId: undefined
},
templateUrl: '../app/fruits/fruitdetails.html',
controller: 'fruitDetailsCtrl as vm'
})
Explanation of States:
start:
url / is entry point of my application. If url is /, start state will be loaded.
fruits:
This state shows list of fruits in my app. Note that there is no url defined for this state. So, if we go to this state, url won't change (State will change, but url won't).
fruits.details:
This state should show detail of a fruit with id fruitId. Notice we have passed fruitId in params. params is used to pass parameters without using the url! So, passing of parameters is sorted. I can write ui-sref="fruit.details({ fruitId: my-fruit-id })" to navigate to fruit.details state and show details of my fruit with fruitId my-fruit-id.
As you might have already got it, the main idea is to use states as means of navigation.
Does my app pass your points?
Navigating between states via UI does not change the URL
Changing the URL does not cause navigation between states, only UI or programmatic actions do (clicking the buttons, etc.)
Hitting F5 restarts the application from "default" controller
Original URL (especially query parameters) must still be accessible
->
pass: as we haven't defined url for states
pass: changing url will change to state to start. The app will not take user to any different state, but it does changes state to start or we could say our default state.
pass: refresh will take you to start state
pass: if you write start in your url, you app will got start state.
Possible work around for the 2nd point, which is not passed completely: We can write code to check the url (in startCtrl controller) passed. If url contains extra things appended to /start, go to previous state. If url is 'start' continue loading start page.
Update:
As pointed by OP #Impworks, solution for 2nd point is also passed if we set url of our start state to /. This way, if we append any string to url, the state won't change.

UI-Router state doesn't work when I'm redirected to my app from Adyen (payment system)

I'm trying to get my app to work with the Adyen payment system. At a certain point I redirect the user to Adyen to make a payment. When the user is done, Adyen redirects to the provided return url. Adyen also adds some query parameters to the url, that are useful to use on the return url page.
This is an example of a url that Adyen redirects to after payment:
http://my.domain/#/payment/result?authResult=AUTHORISED&merchantReference=000220-16402-1459625180&merchantSig=BjeKwBOp70hcsNRD8GUat3fHn4qXxX4Bb2Nxg9RRa04%3D&paymentMethod=mc&pspReference=8614596253051402&shopperLocale=en_GB&skinCode=wMrD9Eei
Now, I want to use UI-Router to get me to the proper page, and load the right controller. Depending on the value in the query parameter authResult, I want to go to a different state. I have created a state for /payment/result?authResult:
$stateProvider.state('payment.result', {
url: '/payment/result?authResult',
templateUrl: IM_APP_DIR + '/views/payment.result.html',
controller: function($state, $stateParams) {
switch ($stateParams.authResult) {
case 'AUTHORISED':
$state.go('payment.authorised');
break;
case 'CANCELLED':
$state.go('payment.cancelled');
break;
etcetera...
}
}
});
Example for the authorised state:
.state('payment.authorised', {
url: '/payment/authorised',
templateUrl: IM_APP_DIR + '/views/payment.authorised.html,
controller: 'PaymentCtrl'
})
Now when I test this and the Adyen test environment redirects met to the url mentioned above, the controller for the /payment/result?authResult state is never entered. (I placed a breakpoint at the line where the switch is defined, but Chrome never gets there.) Instead I get a lot of errors from angular in my console. They mainly say I am getting into an infinite digest loop (https://docs.angularjs.org/error/$rootScope/infdig?p0=10&p1=%5B%5D). I guess that has nothing to do with this problem, since this is also what happened when Adyen redirected to the return url and I had not yet defined any state for the redirect path.
Any ideas what may be wrong with the states I defined, taking the redirect url into account?
Thanks a lot in advance for any help!
Ok, I got it to work eventually. The problem was that I had the parent > child setup in the routing config all wrong. I had also omitted a ui-view directive element in the parent route that the child view could be rendered to.

Angurlarjs: How to represent state in URL and get state back from URL?

I'm working on a search app using AngularJs 1.0.8.
In order to allow bookmarking and sharing links I want to represent the current state of the search in the browser's location bar.
A URL might look like this
http://example.com/#!/search?s="Some query term"&page=2
So the app has to do two things:
update the URL when someone searches
Restore the state when another opens the same URL
What I currently do (maybe this is the wrong approach) is:
Configuring routeProvider to prevent the browsers from reloading on search param changes
...
$routeProvider.when('/search', {
templateUrl: 'app/search/view/List.html',
controller: 'listCtrl',
reloadOnSearch: false
});
...
Getting search results and setting location when someone presses the search button (searchArray holds the search parameters)
...
$location.search(searchArray);
...
Updating the search results accordingly.
...
$scope.search_results=data;
...
In order to restore the state I'm watching $location.search()
...
$scope.$watch(function () { return $location.search() }, function (newVal) {/* evaluate params and fire query */ });
...
My problem is, that location always changes twice. I've managed to overcome this issue by maintaining dirty flag.
As I think this maintaining state in URL is a popular scenario, I think there must be a better approach with Angular.
Could anyone guide me in to the right direction?

Resources