I have an app with angularjs routing, but on some view i want to scroll to some specific div and i use anchorScroll but sometimes (not all times) it refresh all page even i stop event propagation.
Did anyone had this issue?
$scope.redirectTodiv = function(divname,event) {
event.stopPropagation();
event.preventDefault();
$location.hash(divname);
$anchorScroll();
};
Try like this
$scope.redirectTodiv = function(divname,event) {
var id = $location.hash();
$location.hash(divname);
$anchorScroll();
$location.hash(id);
};
The way to ensure navigation with one click is to combine $location.hash() $anchorScroll and setting routeProvider reloadOnSearch property to false i.e.
In your controller code:
$location.hash("editor");
$anchorScroll();
In your route provider:
$routeProvider.when("/masters/voucher", {
templateUrl: "views/card/voucher.html",
reloadOnSearch: false
})
I've two use cases on the same page :
When clicking save, if the response is an error, scroll to the errorDiv that displays the error to the user.
David Kabii's answer did work for me.
However, on the load of the page, in the controller, I want to scroll to a specific area of the page where the user's input is expected. This wouldn't work. I had to use window.setTimeout to workaround this. (there's probably a better way)
window.setTimeout(function(){
$location.hash("anchorForm");
$anchorScroll();
}, 300);
Related
I am using Angular (the $routeProvider, not ui-route), and I have a bug when I have a modal open and try to change the route.
On the route change, since the modal is still open, two bugs happen:
1) I can't scroll.
2) The opacity is at 0.5.
What seems to be happening is the routed event is firing before my jQuery.hide.
I have a workaround, but I feel like this way sucks.
The modal includes two relevant things.
One is a static link. I did this:
// This catches the click on signup from the modal, closes the modal, then
// continues the route change.
$('#modal-signup-link').click(function(event) {
event.preventDefault();
$('#login-modal').modal('hide');
$location.path('/signup');
});
Basically, I created a jQuery on click handler. Works well.
The second portion of the modal allows a user to log in, and I use a service to call the API request. This one required me to use the $timeout to delay the route change (and it seems to work). I feel like this is a BAD solution.
$scope.submit=function() {
console.log('Submit');
Login.login($scope.username, $scope.password).then(function(data) {
if (data.id) {
$('#login-modal').modal('hide');
$timeout(function() {
$location.path('/games');
}, 500)
} else {
$scope.loginData = data.errors.password;
$scope.loginError = true;
$timeout(function() {
$scope.loginError = false;
}, 6000)
}
});
};
Ignore the bottom portion, that's just for handling errors.
When I use the $timeout, the modal closes before the route change, and we're gravy.
Is there a better way to approach this problem?
You can use,$routeChangeStart which gets called on every navigation, or a route change, there you can close your modal.
$rootScope.$on('$routeChangeStart', function() { })
Example:
var app = angular.module('myApp', [])
app.run(["$rootScope","$http","$location",
function($rootScope,$http,$location){
$rootScope.$on('$routeChangeStart', function() {
$('.modal').modal('hide'); // hides all modals
$('#login-modal').modal('hide'); // hides specific modal
angular.element('.modal').hide(); // same as first, but a bit angular way
})
}])
HEre is the documentation of the same.
I am using, Angular.js 1.3, with ui-router.
I have 3 pages, page1.html, page2.html, page3.html.
When user click on page1, page2 will open, but I want to save the scroll state of page 1, where user was before clicking, so that after clicking on back button he lands on same scroll state.
To solve this I opened the page2.html over the page1.html, in iframe, and giving it absolute position to display over the page1.html, and I am using the:
history.pushState({}, '', '/page2.html');
to change the url. This implementation working fine.
Now when user click on link on page2.html, it should open the page3.html, like a normal link, for which I used :
$state.go("page3")
The problem is now the state chages, and page3.html loads, but url is still the /page2.html, url is not changing.
I even tried:
history.pushState({}, '', '/page3.html');
Still url is not changing. Anyone know why it's happening.
Even though the solution you are trying to implement is very creative, I would really choose another direction.
You've got various option, all of which rely on caching the scroll position somewhere. For example:
var scrollTopData = {};
function changeState (toState) {
var currentStateName = $state.current.name;
scrollTopData[currentStateName] = window.scrollY;
$state.go(toState);
}
Then the question remains what to do with the scroll position you have cached. $state.go returns a promise, so a solution would be:
var scrollTopData = {};
function changeState (toState) {
var currentStateName = $state.current.name;
scrollTopData[currentStateName] = window.scrollY;
$state.go(toState).then(function () {
if (toState in scrollTopData) {
window.scrollTo(0, scrollTopData[toState]);
}
});
}
Depending on your implementation, you could also use the answer of asgoth:
I haven't used it before, but angular has a $anchorScroll service. As to reloading the data, you could cache it using $cacheFactory, or store the data on a higher scope.
Another solution would be to use a stateChangeEvent. For example:
$rootScope.$on('$stateChangeSuccess',
function (event, toState, toParams, fromState, fromParams) {
// Do magic
}
);
My advice would be to use the promise returned by $state.go.
You can not have a change in url if you change the default behavior of angular. The part in url after hash changes automatically. You do not have changing urls because you force the browser to /somepage.html
try some thing like /#somepage.html
note the hash(#) added here.
From my AngularJS Home Page I need to scroll to an anchor tag in another page. Both these pages are coming as partial html's into the ng-view component, based on the url. On starting the server, the home page is loaded and from there in need to go to the faq page. I used the normal href with #, but that didn't point to the correct div in the target page. Here is what I tried with $anchorScroll
Here is the controller method
$scope.scrollToFaq = function(id) {
$location.path("/faq")
$location.hash(id);
$anchorScroll();
}
Here is how I use it in the home.html
<a ng-click="scrollToFaq('HERE')" href="" class="link">Here</a>
But this is not working properly. If I load the faq page directly and then come back and click the anchor link from the home page, it works. Is it possible to do this with `$anchorScroll
Try to use Angular's $timeout service.
$scope.scrollToFaq = function(id) {
$location.path("/faq");
$timeout(function(){
$location.hash(id);
$anchorScroll();
}, delay);
here delay would be the time you would like to wait until the anchor scroll happens. I have read about 300ms / 400 ms working for people. When I had this issue, I just had to call the $anchorscroll inside the $timeout. So use what's best for you case.
Note: I am on the lookout for a solution without the use of $timeout. Will update when I find one.
Sounds like a history related issue. If the div has already been loaded once it is found immediatly. This solution worked for me in the past. Maybe an idea to wait for the page to load.
$scope.scrollToFaq = function(id) {
$location.path("/faq");
$(window).on("load", function(){
$location.hash(id);
$anchorScroll();
});
};
Had the same problem. But fixed it :)
Idea is to change to the URL, wait a halfsecond and than jump to the anchor.
HTML:
Links
Controller:
angular.module('exampleApp').controller('NavbarCtrl', function ($scope, $location, $timeout, $anchorScroll) {
$scope.goToAnchor = function(path, anchor){
$location.path('/');
$timeout(function() {
$anchorScroll(anchor);
}, 500);
};
});
Tell me please, how can I disable auto-upto top of my page?
If I use hash nav:
Goto index
my page doest up to top, but if I use AngularJS:
Html:
<a ng-href="#/index">Goto index</a>
JS:
$routeProvider.
when('/index', {
template:'...',
controller: 'RouteCtrl'
})
my page scrolled to top. How can I disable it?
I find it a bit strange that your plain href doesn't scroll and ng-href scrolls, I thought it was the other way round...
But, to the solution; It's up to the browser to scroll on hash changes, so usually to disable it you need to intercept and preventDefault() the event and then change the location by yourself. When using Angular, you can either define some attribute directive for the <a> element or just define your own a directive.
If you use ng-view, it relies on $anchorScroll service with view updates to simulate the behaviour what the browser would normally do, as Angular already intercepts the event. You can prevent the scroll on view load by providing your own $anchorScroll which does nothing:
angular.module('yourModule', []).value('$anchorScroll', angular.noop);
As indicated in the AngularJS documentation, the proper way to do this is:
angular.module('yourModule',[]).config( ['$anchorScrollProvider',
function($anchorScrollProvider) {
$anchorScrollProvider.disableAutoScrolling();
}]
);
just try
assessmentApp.run(['$anchorScroll', function($anchorScroll) {
$anchorScroll = angular.noop;
}])
I use routeProvider to define controlers and templates for my urls.
When I click on the link, which has the same url as is the actual location, nothing happens. I would like the reload() method to be called if a user clicks on such a link even if the location hasn't changed. In other words, if I set the location to the same value, I would like it to behave the same as if I would set it to different value.
Is there a way to configure routeProvider or locationProvider to do it automatically? Or what is the right approach to do this? This is stadard behaviour in round trip applications, but how to do it in angularjs?
I've asked it on google groups as well.
UPDATE:
This question is getting lots of views, so I will try to explain how I solved my problem.
I created a custom directive for linking in my app as Renan Tomal Fernandes suggested in comments.
angular.module('core.directives').directive('diHref', ['$location', '$route',
function($location, $route) {
return function(scope, element, attrs) {
scope.$watch('diHref', function() {
if(attrs.diHref) {
element.attr('href', attrs.diHref);
element.bind('click', function(event) {
scope.$apply(function(){
if($location.path() == attrs.diHref) $route.reload();
});
});
}
});
}
}]);
The directive is then used for all links in my app I want to have this functionality.
<a di-href="/home/">Home</a>
What this directive does is that it sets the href attribute for you based on di-href attribute so angular can handle it like always and you can see the url when you hover over the link. Furthermore when user clicks on it and the link's path is the same as the current path it reloads the route.
Add a / (slash) to the defined url in the route configuration
I met a similar problem today, I have a link in my web page and when I click it, I want the ng-view reload each time, so that I can refresh data from server. But if the url location doesn't change, angular doesn't reload the ng-view.
Finally, i found a solution to this problem. In my web page, I set the link href to:
test
But in the route config, I set:
$routeProvider.when('/test/', {
controller: MyController,
templateUrl:'/static/test.html'
});
The different is the last slash in url. When I click href="#/test" for the first time, angular redirect the url to #/test/, and load ng-view. when i click it second time, because the current url is #/test/, it's not equal to the url in the link (href="#/test") I clicked, so Angular triggers the location change method and reloads the ng-view, in addition Angular redirects the url to #/test/ again. next time i click the url, angular does the same thing again. Which is exactly what I wanted.
Hope this was useful for you.
You can add a _target='_self' on the link to forces the page to reload.
e.g.
{{customer.Name}}
Tested with version 1.0.5 and 1.2.15 on IE and Firefox.
Here's more information from AngularJS site :
Html link rewriting
When you use HTML5 history API mode, you will need different links in different browsers, but all you have to do is specify regular URL links, such as:
link
When a user clicks on this link,
In a legacy browser, the URL changes to /index.html#!/some?foo=bar
In a modern browser, the URL changes to /some?foo=bar
In cases like the following, links are not rewritten; instead, the browser will perform a full page reload to the original link.
Links that contain target element
Example: link
Absolute links that go to a different domain
Example: link
Links starting with '/' that lead to a different base path when base is defined
Example: link
you should use $route.reload() to force the reload.
I don't know if is there a 'automatic' way to do this, but you can use ng-click on these links
For people who are using AngularUI Router. You can use something like this:
<a data-ui-sref="some.state" data-ui-sref-opts="{reload: true}">State</a>
Notice the reload option.
Found the answer here: https://stackoverflow.com/a/29384813/426840
From #Renan Tomal Fernandes answer. following is an example
HTML
<a href="#/something" my-refresh></a>
JS
angular.module("myModule",[]).
directive('myRefresh',function($location,$route){
return function(scope, element, attrs) {
element.bind('click',function(){
if(element[0] && element[0].href && element[0].href === $location.absUrl()){
$route.reload();
}
});
}
});
I think it's a simpler approach.
.directive ('a', function ($route, $location) {
var d = {};
d.restrict = 'E';
d.link = function (scope, elem, attrs) {
// has target
if ('target' in attrs) return;
// doesn't have href
if (!('href' in attrs)) return;
// href is not the current path
var href = elem [0].href;
elem.bind ('click', function () {
if (href !== $location.absUrl ()) return;
$route.reload ();
});
};
return d;
});
Assuming You want to make all basic <a> links (without target attribute) reload on click and You use relative links in the href attribute (e.g. /home instead of http://example.com/home) You don't have to add any special markup to your HTML (comes handy when updating a site with HTML already written).
In my case if the url is same, nothing worked including $route.reload(), $location.path(), $state.transitonTo() etc.
So my approach was Using Dummy Page as follows,
if( oldLocation === newLocation ) {
// nothing worked ------------
// window.location.reload(); it refresh the whole page
// $route.reload();
// $state.go($state.$current, null, { reload: true });
// $state.transitionTo($state.current, $stateParams, {reload:true, inherit: false, notify: false } );
// except this one
$location.path('/dummy');
$location.path($location.path());
$scope.$apply();
}
You need to make '/dummy' module somewhere, the module doesn't do anything, it only change url so that next $location.path() can be
applied. Don't miss $scope.$apply()
I ran into this issue a moment ago, except for it was the home page '/'. I wanted a simple solution with less code. I just took advantage of the .otherwise method in the $routProvider
So in the html link looks like:
Home
since there is no '/home' page specified in the routProvider it will redirect to '/' via the 'otherwise' method. page with this set up:
.otherwise({
redirectTo: '/'
});
Hope it helps someone
I tried Wittaya's solution above using directive approach. Somehow the directive keeps throwing error. I end up with this solution
HTML
Devices
Controller
$scope.stateGo = function (stateName) {
if ($state.$current.name === stateName) {
$state.reload();
} else {
$state.go(stateName);
}
}
Just tried adding this
$(window).on('popstate', function(event) {
//refresh server data
});
and it works fine