I was using AngularJs-1.0.7 and Bootstrap in my application. Recently I migrated from AngularJs-1.0.7 to AngularJs-1.2. I am using Bootstrap\'s Accordions and Tabs.
If you don't success with previous answers, you could try use $timeout... In this case I have used AngularUI tabs...
vm.removeUserTab = function (user) {
$timeout(function () {
vm.activeTab = 0;
var index = vm.userTabs.indexOf(user);
vm.userTabs.splice(index, 1);
});
};
credits to https://prerender.io/js-seo/angularjs-seo-get-your-site-indexed-and-to-the-top-of-the-search-results/
My solution: - inside app.js try adding "$locationProvider.hashPrefix('!');"
.config(['$stateProvider', '$urlRouterProvider', '$httpProvider', '$locationProvider',
function($stateProvider, $urlRouterProvider, $httpProvider, $locationProvider) {
$stateProvider
.state('menu', {
url: '/',
cache: false,
abstract: true,
templateUrl: 'static/www/templates/menu.html'
})
.state('menu.main_page', {
url: 'app/main',
cache: false,
views: {
'menuContent': {
templateUrl: 'static/www/templates/mainpage.html',
controller: 'MainCtrl'
}
}
})
$locationProvider.hashPrefix('!');
$urlRouterProvider.otherwise(function ($injector, $location) {
var $state = $injector.get('$state');
$state.go('menu.mainpage');
});
}])
inside index.html try adding
<meta name="fragment" content="!">
and as Marcel said above
.directive('a', function () {
return {
restrict: 'E',
link: function (scope, elem, attrs) {
if (attrs.href && attrs.href.indexOf('#') > -1) {
elem.on('click', function (e) {
e.preventDefault();
});
}
}
};
})
that's all! works for me!
Your solution in your question does work, but to prevent having to check for each anchor's id, change
if (attrs.href === '#firstTab'|| attrs.href === '#secondTab')
to
if (attrs.href && attrs.href.indexOf('#') > -1)
Directive:
.directive('a', function () {
return {
restrict: 'E',
link: function (scope, elem, attrs) {
if (attrs.href && attrs.href.indexOf('#') > -1) {
elem.on('click', function (e) {
e.preventDefault();
});
}
}
};
})
I would just like to let you know that there is another solution to solve this issue (without defining function in controllers).
You can create a directive that will prevent default browser's behaviour (which is actually changing URL):
var PreventDefault = function () {
var linkFn = function (scope, element, attrs) {
$(element).on("click", function (event){
event.preventDefault();
});
};
return {
restrict: 'A',
link: linkFn
}
};
and then just add the directive to each a
element responsible for toggling a tab like this:
<ul id="myTab" class="nav nav-tabs">
<li class="active"><a href="#firstTab" prevent-default data-toggle="tab">Home</a></li>
<li><a href="#secondTab" prevent-default data-toggle="tab">Profile</a></li>
</ul>
<div id="myTabContent" class="tab-content">
<div class="tab-pane fade in active" id="firstTab">
<p>Content for first tab.</p>
</div>
<div class="tab-pane fade" id="secondTab">
<p>Content For second tab.</p>
</div>
</div>
You can use ng-click to call a function in your JS. In that function, use the event's preventDefault
method, and use $location
's hash
method to change the hash in your URL.
In general you can define functions on the prototype of all scopes by using the rootscope. Add ng-click on your anchor tags and pass the $event to the rootscope handlers. Angular can send the originating event as well with ng-click:
<a ng-click="tabclick($event)">
in a run block of your module you can then set a tabClick function on $rootScope
$rootScope.tabclick = function ($event) { $event.preventDefault(); }
This will work for any scopes and you won't have to check against specific element ids.
Sample fiddle: http://jsfiddle.net/stto3703/wQe6P/
Cheers