change $location search preventing push to history - angularjs

I have a router view with reloadOnSearch: false, it is a search page.
When entering without any search parameter I attempt to set some defaults:
entering in: #/search
I set defaults pars: #/search?currpage=1&pagesize=20
using $location.search({currpage:1,pagesize:20}) the job is done, but I also get the new url pushed in the history, which is as expected, but in this special case it breaks the logic of the navigation flow (clicking back button gets to #/search and again sets defaults and pushes)
Is there a way to replace the search string preventing the history push?

Have you tried to you use the dedicated replace() method ? It prevent to add an history record :
$location.search({currpage:1,pagesize:20}).replace()
Never used it after a $location.search() but it definitely works on $location.path()

Related

Backbone app.navigate control changes to url

I have a backbone application residing at say, http://foo.com. My application behaves different for different region, so say if I navigated to http://foo.com/TX different set of information is loaded, while if I navigate to http://foo.com/OK another set of information is loaded. These necessarily do not form part of the backbone route and are part of the url itself.
I have also modified my backbone route to ignore this second parameter in the url while considering routes in my router initialize function,
routes = [
[/\w+/, 'default', this.default],
[/\w+\/login/, 'login', this.login]
];
_.each(routes, function(route) {
router.route.apply(router,route);
});
But when I do app.navigate("login", true), it changes my URL to http://foo.com/home. What I expect to see is http://foo.com/TX/home, so that it retains the region information. How can I achieve that?
Assuming your app is located at a given location, your router is going to go back to that location, without adding on the extra region code. One option would be to extend your router model and override backbone's navigate function (documentation) to incorporate the region codes, but that could be dangerous and beyond the scope of what you'd like to take on yourself.
Another option is to call the path on your router without updating the URL (documentation). This would run your code and update the page, but would not reset the URL as you desire. with this option, you would want to call the router with the option
router.route.apply("login", {trigger: true, replace: false})

$location.path() vs $location.hash() in angularjs

if my present URL is : xzy.com/#/home/new
$location.hash() gives home/new and $location.path also gives home/new
What is the difference in the two?
If inside the controller of home/new I write $location.hash("#/home/new") or $location.path("/home/new") both do not reload the partial but if I do location.href="#/home/new", it reloads the partial. Why is this?
Also, if inside the partial there is a <a href="#/home/new"> that will also reload the partial.
Why doesn't setting the path/hash reload the partial?
There are two parts to the route.
The first "hash" is really there just for browser compatibility and won't show if you are in HTML5 mode.
For example, given this URL:
http://localhost/spa.htm
If you set:
$location.path('/myPath');
you will get:
http://localhost/spa.htm#/myPath
In this case, the "hash" is just for the browser to hold the URL, the method is path. Note also when you call path without a preceding / it is added, i.e. 'myPath' becomes '/myPath'.
If you subsequently set:
$location.hash('myHash');
You will get:
http://localhost/spa.htm#/myPath#myHash
Finally, let's assume you did not set the path first, then you'll get:
http://locahost/spa.htm#/#myHash
If you are using HTML5 mode, the path is appended without the initial hash.
The first hash is used to append the route, the second is a reference to content on the page. For example, if you use the $anchorScroll service it will respond to what is placed in $location.hash() and not in $location.path().
To summarize:
http://localhost/spa.htm#{path}#{hash}
I had a similar question this morning then Google led me here.
Inspired by other answers and some Googlings I've done, here is my result:
for example, given a browser url:
http://localhost:8080/test.html#!/testpath#testhash%20with%20someothers
in AngularJS ,
url is
/testpath#testhash
path is
/testpath
in another word , from left to right ,path starts at the first character in url and ends at the # or ? or the end of url.
path always start with '/' .so ,if no path is specified ,the path is set as "/" rather than ""
hash is
testhash%20with%20someothers
in another word ,hash starts at the next character of # in url and ends at the end of url
location.href is not implemented in AngularJS. when you say: location.href="#",it behaves like clicking an anchor tag :
click
when invoke the method $location.path,$location.hash as setters, they do change the browser url to match your demands.
And ,why you want AngularJS to RELOAD a page at all? :)
The reason for the second part of your question, why it is not redirecting might be:
You might need to update the binding, with $scope.$apply , this is required when you are using the code other than angular like native javascript, jquery code
for example:
$scope.$apply(function(){
$location.path("#/home/new");
})

$location.search not working if search parameters not changed

$location.search is not reloading route if search parameter are same as parameter in current location.
if window.location is "url#RouteName?param1=value1".
And in some button click calling method which has following code.
$location.path("/RouteName").search({param1 :"value1"});
Then Route is not getting reloaded, how to force reload. I have set reloadOnSeach : true in route config.
$routeProvider.when("RouteName", {templateurl:"pag1.html",controller:"MyCtrl",reloadOnSearch:truee});
reloading the route is not done by $location.search explicitly, in fact it doesn't do anything if the url has not changed by the function call
use
$route.reload()
Reload will realod the route.
In case you want to change the search:
$location.search({'slide_id': slide_id})
If your route params do not change (or change to the same value) then you might need to force the location change:
$scope.$emit('$locationChangeSuccess');
Use window.location.search instead of location.search. It will work.

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?

AngularJS: How to clear query parameters in the URL?

My AngularJS application needs to have access to the user's LinkedIn profile. In order to do that I need to redirect the user to a LinkedIn URL which contains a callback redirect_uri parameter which will tell LinkedIn to redirect the user back to my webapp and include a "code" query param in the URL. It's a traditional Oauth 2.0 flow.
Everything works great except that LinkedIn redirects the user back to the following URL:
http://localhost:8080/?code=XXX&state=YYY#/users/123/providers/LinkedIn/social-sites
I would like to remove ?code=XXX&state=YYY from the URL in order to make it clean. The user does not need to see the query parameters I received from LinkedIn redirect.
I tried $location.absUrl($location.path() + $location.hash()).replace(), but it keep the query params in the URL.
I am also unable to extract the query parameters, e.g. "code", using ($location.search()).code.
It seems like having ? before # in the URL above is tricking Angular.
I use
$location.search('key', null)
As this not only deletes my key but removes it from the visibility on the URL.
I ended up getting the answer from AngularJS forum. See this thread for details
The link is to a Google Groups thread, which is difficult to read and doesn't provide a clear answer. To remove URL parameters use
$location.url($location.path());
To remove ALL query parameters, do:
$location.search({});
To remove ONE particular query parameter, do:
$location.search('myQueryParam', null);
To clear an item delete it and call $$compose
if ($location.$$search.yourKey) {
delete $location.$$search.yourKey;
$location.$$compose();
}
derived from angularjs source : https://github.com/angular/angular.js/blob/c77b2bcca36cf199478b8fb651972a1f650f646b/src/ng/location.js#L419-L443
You can delete a specific query parameter by using:
delete $location.$$search.nameOfParameter;
Or you can clear all the query params by setting search to an empty object:
$location.$$search = {};
At the time of writing, and as previously mentioned by #Bosh, html5mode must be true in order to be able to set $location.search() and have it be reflected back into the window’s visual URL.
See https://github.com/angular/angular.js/issues/1521 for more info.
But if html5mode is true you can easily clear the URL’s query string with:
$location.search('');
or
$location.search({});
This will also alter the window’s visual URL.
(Tested in AngularJS version 1.3.0-rc.1 with html5Mode(true).)
Need to make it work when html5mode = false?
All of the other answers work only when Angular's html5mode is true. If you're working outside of html5mode, then $location refers only to the "fake" location that lives in your hash -- and so $location.search can't see/edit/fix the actual page's search params.
Here's a workaround, to be inserted in the HTML of the page before angular loads:
<script>
if (window.location.search.match("code=")){
var newHash = "/after-auth" + window.location.search;
if (window.history.replaceState){
window.history.replaceState( {}, "", window.location.toString().replace(window.location.search, ""));
}
window.location.hash = newHash;
}
</script>
If you want to move to another URL and clear the query parameters just use:
$location.path('/my/path').search({});
Just use
$location.url();
Instead of
$location.path();
If you are using routes parameters just clear $routeParams
$routeParams= null;
How about just setting the location hash to null
$location.hash(null);
if you process the parameters immediately and then move to the next page, you can put a question mark on the end of the new location.
for example, if you would have done
$location.path('/nextPage');
you can do this instead:
$location.path('/nextPage?');
I've tried the above answers but could not get them to work. The only code that worked for me was $window.location.search = ''
I can replace all query parameters with this single line: $location.search({});
Easy to understand and easy way to clear them out.
The accepted answer worked for me, but I needed to dig a little deeper to fix the problems with the back button.
What I noticed is that if I link to a page using <a ui-sref="page({x: 1})">, then remove the query string using $location.search('x', null), I don't get an extra entry in my browser history, so the back button takes me back to where I started. Although I feel like this is wrong because I don't think that Angular should automatically remove this history entry for me, this is actually the desired behaviour for my particular use-case.
The problem is that if I link to the page using <a href="/page/?x=1"> instead, then remove the query string in the same way, I do get an extra entry in my browser history, so I have to click the back button twice to get back to where I started. This is inconsistent behaviour, but actually this seems more correct.
I can easily fix the problem with href links by using $location.search('x', null).replace(), but then this breaks the page when you land on it via a ui-sref link, so this is no good.
After a lot of fiddling around, this is the fix I came up with:
In my app's run function I added this:
$rootScope.$on('$locationChangeSuccess', function () {
$rootScope.locationPath = $location.path();
});
Then I use this code to remove the query string parameter:
$location.search('x', null);
if ($location.path() === $rootScope.locationPath) {
$location.replace();
}

Resources