web-dev-qa-db-fra.com

Comment empêcher la redirection <a href="#something"> dans Angular Js1.2

J'utilisais AngularJs-1.0.7 et Bootstrap dans mon application. Récemment, j'ai migré de AngularJs-1.0.7 à AngularJs-1.2. J'utilise les accordéons et les onglets de Bootstrap.

Le code HTML pour Tab contient <a href="#id_for_content"> comme indiqué ci-dessous.

<ul id="myTab" class="nav nav-tabs">
    <li class="active"><a href="#firstTab" data-toggle="tab">Home</a></li>
    <li><a href="#secondTab" 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>

Dans les anciennes versions d'Angular, le changement de route n'a lieu que si nous donnons une balise d'ancrage comme <a href="#/firstTab">. Mais AngularJs-1.2 redirige <a href="#firstTab">. Il ne considère pas le / entre # et firstTab. Par conséquent, en cliquant sur Tab, il redirige vers http://web_url/#/firstTab. Comment résoudre ce problème?


Ma solution

J'ai trouvé une solution à ce problème. J'ai écrit une directive pour un tag. Dans cette directive, j'ai vérifié l'attribut href. Si cela correspond, empêchez son comportement par défaut. Vérifiez le code suivant.

app.directive('a', function() {
    return {
        restrict: 'E',
        link: function(scope, elem, attrs) {
            if(attrs.href === '#firstTab'|| attrs.href === '#secondTab'){
                elem.on('click', function(e){
                    e.preventDefault();
                });
            }
        }
   };
}); 

Mais le problème avec cette méthode est que je dois vérifier chaque identifiant de tabulation ou identifiant d'accordéon ici. Si j'utilise des ID dynamiques pour eux, il n'est pas possible de vérifier la directive. 

Si vous pouvez trouver une meilleure solution, faites-le nous savoir à tous.

23
Sajith

Ajoutez simplement ceci à vos liens:

target="_self"

Et tu es prêt;)

46
Vassilis Pits

essayez data-target="#something", cela fonctionne bien pour moi dans les environnements de développement et de production.

19
Sonymon Mishra

Je voudrais juste vous faire savoir qu'il existe une autre solution pour résoudre ce problème (sans définir la fonction dans les contrôleurs).

Vous pouvez créer une directive qui empêchera le comportement du navigateur par défaut (qui modifie en réalité l'URL):

var PreventDefault = function () {

    var linkFn = function (scope, element, attrs) {
        $(element).on("click", function (event){
            event.preventDefault();
        });
    };

    return {
        restrict: 'A',
        link: linkFn
    }
};

puis ajoutez simplement la directive à chaque élément a responsable du basculement d'un onglet comme ceci:

<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>
10
PrimosK

En général, vous pouvez définir des fonctions sur le prototype de toutes les étendues à l'aide de rootscope. Ajoutez ng-click sur vos balises d'ancrage et passez le $ event aux gestionnaires de rootscope. Angular peut également envoyer l'événement d'origine avec ng-click:

<a ng-click="tabclick($event)">

dans un bloc d'exécution de votre module, vous pouvez ensuite définir une fonction tabClick sur $ rootScope

$rootScope.tabclick = function ($event) { $event.preventDefault(); }

Cela fonctionnera pour toutes les portées et vous n'aurez pas à vérifier les identifiants d'élément spécifiques.

Exemple de violon: http://jsfiddle.net/stto3703/wQe6P/

À votre santé

6
Stefan

Vous pouvez utiliser ng-click pour appeler une fonction dans votre JS. Dans cette fonction, utilisez la méthode preventDefault de l'événement, puis la méthode hash de $location pour modifier le hachage de votre URL. 

2
yarons

Cela fait aussi un moment que je suis confronté à ce problème, et je viens de trébucher sur cette question (et votre propre réponse). Il s’avère que votre solution est presque correcte, une simple modification suffit à la faire fonctionner à votre guise.

En plus du problème que vous aviez avec les onglets, je rencontrais également ce problème avec les liens déroulants - ils naviguaient en dehors de la page actuelle lorsque vous cliquez dessus, au lieu de descendre dans le menu - et en fait, ce problème est présent tout lien conçu pour basculer, c’est-à-dire avec l’attribut data-toggle.

Donc, une légère modification de votre code pour vérifier la présence de l'attribut 'toggle' me résout le problème:

app.directive('a', function() {
    return {
        restrict: 'E',
        link: function(scope, elem, attrs) {
            if(attrs.toggle){
                elem.on('click', function(e){
                    e.preventDefault();
                });
            }
        }
   };
});

J'espère que cela t'aides!

1
Tom Spink

Si vous ne réussissez pas avec les réponses précédentes, vous pouvez utiliser $ timeout ... Dans ce cas, j'ai utilisé les onglets AngularUI ...

vm.removeUserTab = function (user) {
    $timeout(function () {
        vm.activeTab = 0;
        var index = vm.userTabs.indexOf(user);
        vm.userTabs.splice(index, 1);
    });
};
0
soreal

crédits à https://prerender.io/js-seo/angularjs-seo-get-your-site-indexed-and-to-the-top-of-the-search-results/

Ma solution: - Dans app.js, essayez d’ajouter "$ 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');
    });
   }])
  • dans index.html essayez d'ajouter 

    <meta name="fragment" content="!">

et comme Marcel a dit ci-dessus

.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();
            });
        }
    }
};
})

c'est tout! travaille pour moi!

0
Eliezer Rhamzfer

Votre solution à votre question fonctionne, mais pour éviter d’avoir à vérifier l’identité de chaque ancre, 

if (attrs.href === '#firstTab'|| attrs.href === '#secondTab')

à

if (attrs.href && attrs.href.indexOf('#') > -1)

Directif:

.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();
                });
            }
        }
    };
})  
0
Marcel