Location search parameters disappear when I load a new template - angularjs

I am using $location.search(params) to store an array in my url. This array has determines how the page will load. It works well only problem is that I have a set of tabs on my page, when ever I click the the tab a new template is loaded with a new controller and the url variables disappear.
I dont understand this behavior $location.search() is not being called again in the new controller. How can I get the Url to stay static?

In the $routeProvider set reloadOnSearch: false so you don't reload when $location.search() changes.
https://docs.angularjs.org/api/ngRoute/provider/$routeProvider

Change the path using
$location.path('/differentRoute').search(params);
Doing so would change the route and set the search parameters again.

Related

In Angular how to change the route template using a controller function?

When loading the url at first, I need to display the initial template. But after clicking a link, I need to
Get it's href value (It's the current template url with some extra params)
Send the new url with params to the server
Get the new template (The server will send a new template with new data)
Change the view accordingly (Update the whole page)
I have managed to complete the first task. The 4th task is the real problem. Changing the route's template using the function which gets called when clicking the link (With ng-click). How can I do it?
All you need to do in order to replace current template with the new one is basically two lines of code. Namely:
update current $templateCache for the currently used template;
reload current route.
It could look something like this:
var content = '<h2>New content loaded previously</h2>';
var templateName = $route.current.templateUrl;
$templateCache.put(templateName, content);
$route.reload();
Check the simple demo: http://plnkr.co/edit/V5AG0UXS3b8wBwxrz7qO?p=preview
To get the URL of your current template :
$route.current.templateUrl
You can try to set template value directly (never test)
$route.current.templateUrl = "http://myrul.tld";
You can see the doc at https://docs.angularjs.org/api/ngRoute/service/$route

How to prevent Angular from turning URL hash into a path

I have an angular app with a number of links. Clicking each link displays a particular set of data. I would like each link to set a hash in the URL, like http://foo.com/bar#item1, and I'd also like to show the page with the particular set of data displaying when that URL with the hash is accessed directly.
I was hoping to do it by reading / manipulating the $location.hash(), but as soon as I inject $location into my controller, the #item1 in the URL changes to #/item1. Is there a way to prevent Angular from doing this, and what's the best way of setting up what I described?
You could pass parameters in the routes /bar/item1, catch it with $routeParams and if exist make $location.hash().
"controller"
var anchor = $routeParams.anchorBottom;
if(anchor){
$location.hash(anchor);
$anchorScroll();
}
"link to section"
$location.path('/heart/bottom');
"route"
.when('/heart/:anchorBottom',{
You could see this running here.

$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.

Updating URL in Angular JS without re-rendering view

I'm building a dashboard system in AngularJS and I'm running into an issue with setting the url via $location.path
In our dashboard, we have a bunch of widgets. Each shows a larger maximized view when you click on it. We are trying to setup deep linking to allow users to link to a dashboard with a widget maximized.
Currently, we have 2 routes that look like /dashboard/:dashboardId and /dashboard/:dashboardId/:maximizedWidgetId
When a user maximizes a widget, we update the url using $location.path, but this is causing the view to re-render. Since we have all of the data, we don't want to reload the whole view, we just want to update the URL. Is there a way to set the url without causing the view to re-render?
HTML5Mode is set to true.
In fact, a view will be rendered everytime you change a url. Thats how $routeProvider works in Angular but you can pass maximizeWidgetId as a querystring which does not re-render a view.
App.config(function($routeProvider) {
$routeProvider.when('/dashboard/:dashboardId', {reloadOnSearch: false});
});
When you click a widget to maximize:
Maximum This Widget
or
$location.search('maximizeWidgetId', 1);
The URL in addressbar would change to http://app.com/dashboard/1?maximizeWidgetId=1
You can even watch when search changes in the URL (from one widget to another)
$scope.$on('$routeUpdate', function(scope, next, current) {
// Minimize the current widget and maximize the new one
});
You can set the reloadOnSearch property of $routeProvider to false.
Possible duplicate question : Can you change a path without reloading the controller in AngularJS?
Regards
For those who need change full path() without controllers reload
Here is plugin: https://github.com/anglibs/angular-location-update
Usage:
$location.update_path('/notes/1');
I realize this is an old question, but since it took me a good day and a half to find the answer, so here goes.
You do not need to convert your path into query strings if you use angular-ui-router.
Currently, due to what may be considered as a bug, setting reloadOnSearch: false on a state will result in being able to change the route without reloading the view. The GitHub user lmessinger was even kind enough to provide a demo of it. You can find the link from his comment linked above.
Basically all you need to do is:
Use ui-router instead of ngRoute
In your states, declare the ones you wish with reloadOnSearch: false
In my app, I have an category listing view, from which you can get to another category using a state like this:
$stateProvider.state('articles.list', {
url: '{categorySlug}',
templateUrl: 'partials/article-list.html',
controller: 'ArticleListCtrl',
reloadOnSearch: false
});
That's it. Hope this helps!
We're using Angular UI Router instead of built-in routes for a similar scenario. It doesn't seem to re-instantiate the controller and re-render the entire view.
How I've implemented it:
(my solution mostly for cases when you need to change whole route, not sub-parts)
I have page with menu (menuPage) and data should not be cleaned on navigation (there is a lot of inputs on each page and user will be very very unhappy if data will disappear accidentally).
turn off $routeProvider
in mainPage controller add two divs with custom directive attribute - each directive contains only 'templateUrl' and 'scope: true'
<div ng-show="tab=='tab_name'" data-tab_name-page></div>
mainPage controller contains lines to simulate routing:
if (!$scope.tab && $location.path()) {
$scope.tab = $location.path().substr(1);
}
$scope.setTab = function(tab) {
$scope.tab = tab;
$location.path('/'+tab);
};
That's all. Little bit ugly to have separate directive for each page, but usage of dynamic templateUrl (as function) in directive provokes re-rendering of page (and loosing data of inputs).
If I understood your question right, you want to,
Maximize the widget when the user is on /dashboard/:dashboardId and he maximizes the widget.
You want the user to have the ability to come back to /dashboard/:dashboardId/:maximizedWidgetId and still see the widget maximized.
You can configure only the first route in the routerConfig and use RouteParams to identify if the maximized widget is passed in the params in the controller of this configured route and maximize the one passed as the param. If the user is maximizing it the first time, share the url to this maximized view with the maximizedWidgetId on the UI.
As long as you use $location(which is just a wrapper over native location object) to update the path it will refresh the view.
I have an idea to use
window.history.replaceState('Object', 'Title', '/new-url');
If you do this and a digest cycle happens it will completely mangle things up. However if you set it back to the correct url that angular expects it's ok. So in theory you could store the correct url that angular expects and reset it just before you know a digest fires.
I've not tested this though.
Below code will let you change url without redirection such as: http://localhost/#/691?foo?bar?blabla
for(var i=0;i<=1000;i++) $routeProvider.when('/'+i, {templateUrl: "tabPages/"+i+".html",reloadOnSearch: false});
But when you change to http://localhost/#/692, you will be redirected.

Resources