Angular navigate to a specific tab on a page - angularjs

I would like to navigate to a page of my single page application using a link like /#/invoices/1?tab=2. This page contains tabs, so I would also like to send the user directly to the tab I wish through the url.
Could you provide some pointers on how to implement this in the cleanest way?

Use $anchorScroll method, passing a class name on it you can go directly to that element.

Just an update to above answer.
Few examples with custom directives
http://nadeemkhedr.com/angularjs-scroll-to-element-using-directives/
angular.module('MyApp').directive('scrollToBookmark', function() {
return {
link: function(scope, element, attrs) {
var value = attrs.scrollToBookmark;
element.click(function() {
scope.$apply(function() {
var selector = "[scroll-bookmark='"+ value +"']";
var element = $(selector);
if(element.length) {
window.scrollTo(0, element[0].offsetTop – 100);
// Don’t want the top to be the exact element, -100 will go to the top for a little bit more
}
});
});
}
};
});

Related

Get Rendered Form into $StateChangeStart

Is there any way that I can get the rendered form into
$rootScope.on("$stateChangeStart", function (){
})
I tried two things.
First: Using $template Request I got the template using templateURL and compiled that but it renders predefined template not the DOM's rendered.
See the code
if (fromState.name.length > 0) {
$templateRequest(fromState.templateUrl)
.then(function (html) {
var compiledElement = $compile(html)($rootScope);
var compliedForm = compiledElement.find('form');
}
}
then Secondly, I tried using
angular.element('document').find('form');
But it gives me list of attribute and all. But how to get check form is valid or not.
Document
I think what you are trying to achieve, is to block a state change when a form in the current view is not valid. I would make a directive for this, something like:
app.directive("formValidStateCheck", function($rootScope) {
return {
restrict: "A",
require: "ngForm",
link: function(scope, element, attrs, ngFormCtrl) {
$rootScope.$on("$stateChangeStart", function(event) {
if (ngFormCtrl.$invalid) {
// prevent routing
if (!confirm("Are you sure"))
event.preventDefault();
}
}
});
}
}
});
Than put the directive on your forms:
<form ng-form="myForm" form-valid-state-check>
</form>
.find() method will not work with selectors and tag names. you need to get it by form id(for this have a id to the form).
Then use angular.element(document.getElementById("#form_id"));

Create a nested fallback src for an Image using angularjs directive

In my tag if the src returns a 404 then I can display a fallback image using directives, but if this fallback image is also returns 404 the how can I show another image using directive
Create a directive to go through a series of error images and provide them one after the other.
You can provide alternative image urls in the tag itself.
<img fallbacksrc="http://url1/error.jpg,http://url2/error.jpg" src="http://url0.image.jpg">
Then write a directive for fallbacksrc and bind the tag for error event. Use split function to alternative images in to an array. You can then choose from this array inside the link function.
The information you are looking for is that the error event will occur any number of times as long as the src fails. So there is no limit for this to occur if all the images you are setting inside the directive fails continuously.
Here is a sample code. I'm using an array of error images in the scope itself in this example without providing them inside the tag.
function MyCtrl($scope) {
$scope.image = "http://greentreesarborcareinc.com/wp-content/uploads/2014/01/image-placeholder.jpg1"
$scope.errorImageIdx = 0;
$scope.errorImages = ["http://spanning.com/assets/uploads/images/11954453151817762013molumen_red_square_error_warning_icon.svg_.med_.png", "http://fivera.net/wp-content/uploads/2014/03/error_z0my4n.png"]
}
myApp.directive('fallbacksrc', function() {
return {
link: function(scope, ele) {
ele.bind('error', function() {
if (scope.errorImageIdx <= scope.errorImages.length - 1) {
angular.element(this).attr("src", scope.errorImages[scope.errorImageIdx]);
scope.errorImageIdx++;
}
});
}
}
});
Here the tag will try to display the image referenced in $scope.image. But that is invalid. So, it tries to load the images from the array.
Try setting the first element of the array to something invalid. It will automatically select the second image in this case.
You can create angular directive like this -
app.directive('onError', function() {
return {
restrict:'A',
link: function(scope, element, attr) {
element.on('error', function() {
element.attr('src', attr.onError);
})
}
}
});
And use like -
<img class="pic" on-error="default-image.jpg" ng-src="{{author.profileImageUrl}}">

Floating title is not working in Angularjs

I have a list of item with two iterations. I want a sticky title when the title scroll up from the view area. I have done it with jquery, but can't able to do in angular. Created a fiddle https://jsfiddle.net/1vf5ska7/
I just to want to add a class in tag when the title is goes up to the view area.
angular.element(document.querySelector('#l-content__desc__split1__body')).on('scroll', function() {
});
And the important thing is it is not a window scroll. It's a div scroll
Please help me.
Thanks..
You need to include a directive and operate on it. If $window.pageYOffset is greater than the position of the element you apply a specific class to that element which is positioned fixed.
var app = angular.module('app', []);
app.directive('setClassOnTop', function ($window) {
var $win = angular.element($window); // wrap window object as jQuery object
return {
restrict: 'A',
link: function (scope, element, attrs) {
var title = angular.element(document.getElementById('sticky-title'));
var offsetTop = title[0].offsetTop;
$win.on('scroll', function (e) {
if ($window.pageYOffset > offsetTop) {
angular.element(title[0]).addClass('floating-title');
} else {
angular.element(title[0]).removeClass('floating-title');
}
});
}
};
});
And here is the updated fiddle:
https://jsfiddle.net/1vf5ska7/3/

override angular ui-router for links to page anchors

I have links to anchors on my page (a href="#idea"). ui-router obviously overrides them. Is there a way to use both in harmony? Thank you.
https://gist.github.com/anonymous/2880f2f2c9f91b0b695f#file-gistfile1-txt
Well you aren't supposed to use it on a href this way, instead you should add it like the following:
...
You can see an example of this at the bottom of the $anchorScroll API here.
If you want to combine ui-router with anchor tag, I solved my problem using this code
<a ui-sref="routename({'#': 'ownerfeatures'})">Link</a>
Hi I had similar problem with anchors.
Since I want to go on using regular HTML syntax (href="#may-hash") I've made a directive which looks if a link is an anchor and if yes perform scroll operations. See detailed code :
/**
* Ressource : https://docs.angularjs.org/api/ng/service/$anchorScroll
*/
.directive('a', ['$location', '$anchorScroll', function ($location, $anchorScroll) {
return {
restrict: 'E',
link: function (scope, elem, attrs)
{
// href should be defined and not empty
if(typeof attrs.href!=='undefined' && attrs.href.length > 0)
{
// href should be an anchor
if(attrs.href.substring(0, 1) === '#')
{
elem.on('click', function (e)
{
// if current hash is different from requested hash
// then set new hash
// no need to call $anchorScroll()
// since scroll is auto if you've not used $anchorScroll.disableAutoScrolling()
if ( '#' + $location.hash() !== attrs.href)
{
$location.hash(attrs.href);
}
// if hash is the same, force scroll
else
{
$anchorScroll();
}
});
}
}
}
};
}])
Better way to do this is this way
say you are on state app.state1.child and your anchor tag is #list, so say that you a tag use this code
<a ui-sref="app.state1.child#list">Link</a>
I know is an old topic but always get stuck looking a better solution to do the anchoring in my apps.
Today I was looking to scroll in the same page and tested a lot of differents solutions. Most of the time this one is the general recommendation:
<a ui-sref="routename({'#': 'ownerfeatures'})">Link</a>
The problem with this one is works to transition to a new state and go to the anchor but doesn't work well if you want to just scroll in the same page, because it only works the first click.
Then I realize that the use of $anchorScroll should be great for this and I made this directive maybe can help someone. Note I didn't use location.hash, because I don't want to add the hash to my address bar and also there where some situations in my flow that make the screen scroll when not required.
function anchorScroll($anchorScroll){
return {
restrict: 'A',
scope: {
target: '=anchorScroll'
},
link: function ( scope, element, attrs ) {
element.bind('click', function(event) {
console.log(scope.target)
$anchorScroll(scope.target);
})
}
}
}
But the also there is a very simplest way, just using $anchorScroll in the template. In your controller:
$scope.anchorScroll = $anchorScroll;
And in the view:
Scroll to ID

angularjs have a directive only apply for select controllers

I'm using a directive to implement scrolling on a page from an a to a div. Meaning that by clicking on an a looks like:
<a data-scroll-on-click="" href="#projects">Projects</a>
The page smoothly scrolls to:
<div id="projects">
To make this happen, I am using an attribute scroll-on-click via the following directive:
consortiumApp.directive('scrollOnClick', function() {
return {
restrict: 'A',
link: function(scope, element, attrs) {
var idToScroll = attrs.href;
element.on('click', function(event) {
event.preventDefault();
var $target;
if (idToScroll) {
$target = $(idToScroll);
} else {
$target = element;
}
$("body").animate({scrollTop: $target.offset().top}, 1500, 'easeInOut
});
}
}
});
The preventDefault stops the router from kicking in.
The a with the data-scroll-on-click attribute is part of a navbar that I would like to include on other pages via ng-include. However, this means that the a element will have the scroll-on-click attribute on pages where scrolling does not make sense. Meaning that when the navbar is on other pages besides the main page, I want the anchors in it to function like links back to the main page and not to trigger scrolling.
I'm not sure what a good solution is: I'm not sure if it is possible to have scroll-on-click appear only when there is a certain active controller (a sort of conditional attribute)? Or if it is possible to indicate the current active controller in a directive?
Worst comes to worst, I will just write two navbars - one for the main page that implements scrolling via a directive and one for subsidiary pages that implements linking via the router, but I have a feeling there is a more concise way to do this.
I think you can pass boolean value along with the data-scroll-on-click='true/false' and check this in the directive if its true than proceed for scroll otherwise ignore it.
<a data-scroll-on-click="" href="#projects">Projects</a>
And
consortiumApp.directive('scrollOnClick', function() {
return {
restrict: 'A',
link: function(scope, element, attrs) {
var idToScroll = attrs.href;
var scroll_needed = attrs.scrollOnClick;
if(scroll_needed === true){
element.on('click', function(event) {
event.preventDefault();
var $target;
if (idToScroll) {
$target = $(idToScroll);
} else {
$target = element;
}
$("body").animate({scrollTop: $target.offset().top}, 1500, 'easeInOut
});
}
}
}
});

Resources