AngularJS UI-Router scroll to top after state change - javascript

My page should scroll to top again after i change the page.
I have an angular1.6 page with page transitions & ui-router, so i cant use <div ui-view="main" autoscroll="true"></div>. I tried the following code but its not even executing the console.log :/ :
angular.module("App", ["ngAnimate", "ui.router", "vcRecaptcha"]).run(["$rootScope", "$state", function(a, b) {
a.$on('$stateChangeSuccess',function(){
window.scrollTo(0,0);
console.log("foo");
})
}])
I tried routeChangeSuccess too ... any ideas?
Thanks in advance

If you are using the new ui-router (v1.0.0), the $stateChange* events will not work. You must use $transitions.on* hooks from now on.

Related

angular-translate display key

In my app I use the angular translate .
On my index.html I put the directive translate-cloak class="translate-cloak" with .translate-cloak {visibility: hidden;} on <body> but for the <div ui-view></div> content the key is display before my tranlsted text.
In my controller I try to do
function SearchCtrl ($translatePartialLoader, $translate) {
$translatePartialLoader.addPart('../components/search');
$translate.refresh();
$translate.onReady().then(function(){
alert($translate.instant('SEARCH_MONTH')); #display SEARCH_MONTH and not the content
...
How can I wait the loading of the module before to render my view ?
Thanks
To wait until your file gets downloaded you have to do following:
$translatePartialLoader.addPart('../components/search');
$translate.refresh().then( /* Do your work here */ );
Thank you, sandyJoshi! After spending a lot of time trying to figure out how to solve the issue, your solution came out. It was implemented this way:
$translatePartialLoader.addPart('file-upload-js');
$translate.refresh().then(
// detecting a hash/anchor change using jQuery: http://www.rcneil.com/force-reload-on-a-hash-or-anchor-change-with-jquery/
$(window).on('hashchange',function(){
window.location.reload(true);
})
);

AngularJS ui view autoscroll not working

I'm using Angular's ui-router but having a problem where when I click on a new view, the page doesn't start at the top but where it was. I set autoscroll to true in my ui-view like what others suggested but it still isn't working. I'm not sure what the reason is for it not working.
<ui-view autoscroll="true" />
The default option is true, maybe there's something preventing the autoscroll from firing, we need more code. Also you can make a custom code that'll work. Something like this
$scope.$on('$routeChangeSuccess', function () {
window.scrollTo(0, 0);
});
As you will see at this other SO Post '$routeChangeSuccess' will not work. You need to change the code to look like this:
$scope.$on('$stateChangeSuccess', function () {
window.scrollTo(0, 0);
});
Helpful UI-Router references (some gleaned from the referred-to SO Post):
State Change Events: https://github.com/angular-ui/ui-router/wiki#state-change-events
View Load Events: https://github.com/angular-ui/ui-router/wiki#view-load-events

AngularJS: Getting stale results for element dimensions in a directive (1.2 vs 1.3)

I'm fairly new to Angular and am having trouble adding directives to watch the size of elements in response to changes in the page layout.
I'm using a custom directive based on some good examples from a similar question: AngularJS: Better way to watch for height change , but I've found the watch is seeing the dimensions of the target element before the panel is resized - I assume because the directive runs before the browser renders the changes.
I've put together a JSFiddle showing the problem. http://jsfiddle.net/aW9dU/139/ . On hitting the 'toggle' button it should update the displayed header dimensions to match the new state of the page. Currently it is showing the previous height of the element. If the $timeout is uncommented then the update loop is triggered.
HTML:
<div ng-app='myApp' ng-controller='myCtrl'>
<div id="header" el-size='headerSize'>
<button id='panelToggle' ng-click="panelToggle = !panelToggle">toggle</button>
<div id='panel' ng-show='panelToggle'>Panel content. Toggle me!</div>
</div>
<div>Header dimensions: {{headerSize}}</div>
</div>
JavaScript:
angular.module('myApp', [])
.directive('elSize', ['$timeout', function ($timeout) {
return {
link: function (scope, elem, attrs) {
scope.$watch(function (newVal, oldVal) {
//$timeout(function () {
console.log(elem[0].offsetWidth, elem[0].offsetHeight);
scope[attrs.elSize] = {
width: elem[0].offsetWidth,
height: elem[0].offsetHeight
};
//});
});
}
}
}])
.controller('myCtrl', function ($scope) {
$scope.panelToggle = true;
});
The suggested solution I've found is to use a $timeout to postpone evaluation until after the page has re-rendered but doing this triggers an infinite update loop which can be seen in the console after uncommenting the $timeout line.
What have I missed?
Update:
As pointed out below, this works in Angular 1.2.x but breaks in 1.3 (1.3.0, 1.3.5, 1.3.8). The 1.2 to 1.3 migration guide doesn't appear to mention anything that might explain the change.

Angular + Semantic UI Form Validations not woking [duplicate]

I have a simple website that implements jQuery in order to create a Slider with some images in the Index.html top banner.
Now, I want to use AngularJS so I'm breaking the HTML code into separate partials.
Header
Footer
Top Banner
If I run the Index.html in the original version (without applying AngularJS patterns) then I can see the slider working perfect.
When applying AngularJS patterns, I moved the top banner HTML to a partial html and then applied ng-view to the div where the top banner is originally located.
var app = angular.module('website', ['ngRoute']);
app.config(function($routeProvider) {
$routeProvider.
when('/about',{templateUrl:'app/partials/about.html'}).
when('/contact',{templateUrl:'app/partials/contact.html'}).
otherwise({redirectTo:'/home',templateUrl:'app/partials/home.html'})
});
When I refresh the page the slider is not working, is rendered as simple html without any jQuery effect, is really a mess.
This partials has some jQuery plugins that usually activates by document.ready. But this event not fire when angular load partial in ng-view. How can i call this event to initialize jQuery plugins?
Any clue how to fix this?
Appreciate any help.
When you specify your routes, you can also specify a controller, so your routes would look like this:
var app = angular.module('website', ['ngRoute']);
app.config(function($routeProvider) {
$routeProvider.
when('/about',{templateUrl:'app/partials/about.html', controller: 'aboutCtrl'}).
when('/contact',{templateUrl:'app/partials/contact.html', controller: 'contactCtrl'}).
otherwise({redirectTo:'/home',templateUrl:'app/partials/home.html', controller: 'homeCtrl'})
});
Now, you can define inside each controller what you want to do, jquery-wise, as part of a function, like this:
angular.module('website').controller('aboutCtrl', ['$scope', function ($scope) {
$scope.load = function() {
// do your $() stuff here
};
//don't forget to call the load function
$scope.load();
}]);
Make sense?
The other provided answers will work, but they are bound to controllers, and therefore not as scalable and reusable.
To do it the real "Angular" way as mentioned in the comments, you should be using a directive. The benefit to this is that you're able to create several instances with the same code, and can pass in attributes to the directive logic to "customize" the directive. Here's a sample of a way I've used it using bxSlider plugin:
JS:
app.directive('slider', ['$rootScope', function($rootScope) {
return {
restrict: 'EA',
templateUrl: '/path/to/template',
link: function(scope, iElement, attrs) {
//attrs references any attributes on the directive element in html
//iElement is the actual DOM element of the directive,
//so you can bind to it with jQuery
$(iElement).bxSlider({
mode: 'fade',
captions: true
});
//OR you could use that to find the element inside that needs the plugin
$(iElement).find('.bx-wrapper').bxSlider({
mode: 'fade',
captions: true
});
}
};
}]);
HTML:
<div slider some-attibute="some-attribute"></div>
And inside your directive template you could have the slider wrapper and slides, which you could build dynamically using ng-repeat bound to scope data.
I'd recommend reading this excellent article by Dan Wahlin about creating custom directives and how to fully harness they're power.
I had the same problem, I was loading some nav links in a ng-include and I have a script file called on my index.html with jquery instructions to make links active and It i not see the included content.
I tried all of the above solutions and for some reasons, none of them worked for me. When the content is not included (straight in the index.html) jquery kicks in fine but once included it stopped recognizing my elements.
So I simply wrapped my instructions in a setTimeout() function and it worked! Maybe it'll work for you too?
setTimeout(function() {
$("nav ul li").click(function() {
$("nav ul li").removeClass('active');
$(this).addClass('active');
});
});
Somehow the setTimeout() manages to load the script AFTER angular is done loading included content.
Happy coding everyone !
A Directive is certainly a good option, but you can also add a controller to any partial, which will perform all tasks (also with jQuery if you want) after the partial is loaded:
Example: partials/menu.html
<div ng-controller="partialMenuCtrl">
...
</div>
I had the same issue, I was running Jquery slick slider in simple html page it was working fine. How it works basically by including the slick.min.js file underneath the jquery.min.js file and then in script tags you need to initialize the plugin with options like e.g.
$('.items').slick({
infinite: true,
slidesToShow: 3,
slidesToScroll: 3
});
now coming back to the issue, when I added Angular JS to my page and made partials of the page and then went back to the browser to check weather the page was working fine or not, the page was working fine except the slider. Then I tried to move those slick.min.js and plugin initialization to the partials, and it worked :)
How it worked I don't know the reason, since I am new to Angular but it worked and I am still wondering the reason.
I know it is an old thread but just for the sake of completion, you can use the following JQuery code. It is called event Delegation.
$("#anyDivOrDocument").on('click', '#targetDiv', function(event) {
event.preventDefault();
alert( 'working' );
});
I bought a html5 template and tried to integrate with my angularJS web app. I encountered the same issue. I solved it using:
Put the code below at where you put your <script src="vendor/61345/js/script.js"></script> code.
<script>
document.write('<script src="vendor/61345/js/script.js"><\/script>');
</script>

AngularJS: how to know when the $compile has finished?

http://plnkr.co/edit/GRVZl35D1cuWz1kzXZfF?p=preview
In the custom fancybox (aka lightbox, a dialog) I show contents with interpolated values.
in the service, in the "open" fancybox method, i do
open: function(html, $scope) {
var el = angular.element(html);
$compile(el)($scope); // how to know when the $compile is over?
$.fancybox.open(el); // the uncompiled is shown before the compiled
}
The problem is that the content in the dialog is loaded before the end of the $compile, so after less than a second i got a refresh of the dialog content with the values.
The plunkr works, but i want to avoid that the "el" is shown before it gets totally compiled: i want to show it only after the $compile has finished his job
Is there a way to know when the $compile it's over so i'll show the content on fancybox only after that?
You can't inject $scope into services, there is nothing like a singleton $scope.
So instead of $compile(el)($scope); try:
var compiledEl = $compile(el);
....
The $compile returns compiled data.
as a side note
I would provide service to directive and compile it into directive instead. I think it's the right way.
I've had the same problem with the ngDialog modals and popup provider. I needed to position the dialog based on its height. But the height depended on the compiled DOM.
I eventually found a solution using $timeout, like described in that post: http://blog.brunoscopelliti.com/run-a-directive-after-the-dom-has-finished-rendering/
For your code, it would give something like that:
open: function(html, $scope) {
var el = angular.element(html);
$compile(el)($scope);
$timeout(function() {
$.fancybox.open(el);
}, 0);
}

Categories

Resources