Comment / quand utiliser ng-click pour appeler un itinéraire?

243

Supposons que vous utilisez des itinéraires:

// bootstrap
myApp.config(['$routeProvider', '$locationProvider', function ($routeProvider, $locationProvider) {

    $routeProvider.when('/home', {
        templateUrl: 'partials/home.html',
        controller: 'HomeCtrl'
    });
    $routeProvider.when('/about', {
        templateUrl: 'partials/about.html',
        controller: 'AboutCtrl'
    });
...

Et dans votre html, vous souhaitez accéder à la page à propos lorsqu'un bouton est cliqué. Une façon serait

<a href="#/about">

... mais il semble que ng-click serait utile ici aussi.

  1. Cette hypothèse est-elle correcte? Que ng-click soit utilisé à la place de l'ancre?
  2. Si oui, comment cela fonctionnerait-il? C'EST À DIRE:

<div ng-click="/about">

Robert Christian
la source
ui-sref Voir cette réponse: stackoverflow.com/a/21105057/2539811
Vincil Bishop

Réponses:

430

Les itinéraires surveillent le $locationservice et répondent aux changements d'URL (généralement via le hachage). Pour "activer" un itinéraire, vous changez simplement l'URL. La façon la plus simple de le faire est d'utiliser des balises d'ancrage.

<a href="#/home">Go Home</a>
<a href="#/about">Go to About</a>

Rien de plus compliqué n'est nécessaire. Si, cependant, vous devez le faire à partir du code, la bonne façon est d'utiliser le $locationservice:

$scope.go = function ( path ) {
  $location.path( path );
};

Ce qui, par exemple, pourrait déclencher un bouton:

<button ng-click="go('/home')"></button>
Josh David Miller
la source
6
Celui-ci n'a pas fonctionné pour moi, mais en remplaçant $ location.hash (hachage); avec $ location.path (hachage); Ça marche. Ceci est suggéré par @sean dans une autre réponse, qui a beaucoup moins de votes pour une raison quelconque.
Per Quested Aronsson
2
@PerQuestedAronsson pathet hashservent à deux fins différentes, mais selon les circonstances peuvent avoir le même effet. Dans la plupart des cas, pour un routage strict (en particulier avec html5modeactivé), ce pathsera le choix canonique. J'ai mis à jour la réponse pour refléter cela.
Josh David Miller
2
@DavidWoods Cela devrait fonctionner, mais seulement si le chemin de base correspond /. Si vous diffusez l'application depuis /app/index.html, cela ne fonctionnera pas car l'URL absolue est /app/next.html. Évidemment, le serveur doit également être configuré pour renvoyer votre index.htmlfichier lorsqu'il est atteint /next.html. N'hésitez pas à poster un Plunker / Fiddle si vous voulez que j'y jette un œil.
Josh David Miller
2
C'est une chose très générique et utile à faire. Existe-t-il un moyen de le centraliser, ou devons-nous vraiment ajouter une gométhode à chaque contrôleur? (Ou créer un contrôleur racine avec une gométhode?)
Bennett McElwee
3
@BennettMcElwee Je pense que la meilleure approche est de loin d'utiliser simplement des balises d'ancrage; la balise bouton ne fournit aucune valeur dans ce cas et est ce qui crée le problème. Cela dit, vous pouvez facilement créer une directive pour le faire pour vous, par exemple: <button click-go="/home">Click</button>. La fonction de lien ne serait que celle-ci:element.on("click", function () { $location.path(attrs.clickGo); });
Josh David Miller
83

Voici un excellent conseil que personne n'a mentionné. Dans le contrôleur dans lequel se trouve la fonction, vous devez inclure le fournisseur de localisation:

app.controller('SlideController', ['$scope', '$location',function($scope, $location){ 
$scope.goNext = function (hash) { 
$location.path(hash);
 }

;]);

 <!--the code to call it from within the partial:---> <div ng-click='goNext("/page2")'>next page</div>
sean
la source
2
cool merci! cette réponse a mieux fonctionné pour moi, car la méthode de hachage ajoute les valeurs sur l'url (encodée) et la méthode du chemin me permet de remplacer l'URL complète, c'est ce dont j'avais besoin. Merci!
jfplataroti
8
C'est la seule solution suggérée sur cette page qui a réellement fonctionné. Je ne sais pas pourquoi une autre réponse a beaucoup plus de votes que celle-ci ..?
Per Quested Aronsson
J'essayais cela, mais cela ne fonctionne pas. Dois-je également ajouter un emplacement au module avant de le fixer au contrôleur?
Fallenreaper
Cela a fonctionné pour moi une fois que j'ai défini ng-click sur un div plutôt que sur un <a>.
Steve
33

L'utilisation d'un attribut personnalisé (implémenté avec une directive) est peut-être le moyen le plus propre. Voici ma version, basée sur les suggestions de @Josh et @ sean.

angular.module('mymodule', [])

// Click to navigate
// similar to <a href="#/partial"> but hash is not required, 
// e.g. <div click-link="/partial">
.directive('clickLink', ['$location', function($location) {
    return {
        link: function(scope, element, attrs) {
            element.on('click', function() {
                scope.$apply(function() {
                    $location.path(attrs.clickLink);
                });
            });
        }
    }
}]);

Il a quelques fonctionnalités utiles, mais je suis nouveau dans Angular, il y a donc probablement matière à amélioration.

Bennett McElwee
la source
Cela ne créera-t-il pas un événement de clic sur l'élément chaque fois que l'attribut clickLink change?
toxaq
@toxaq Ce n'est certainement pas parfait. Je soupçonne que lorsque l' clickLinkattribut change, la directive ajoute le nouveau gestionnaire de clics mais laisse l'ancien en place. Le résultat pourrait être un peu chaotique. À l'origine, j'ai écrit ceci pour l'utiliser dans une situation où l' clickLinkattribut ne changerait jamais, donc je n'ai jamais attaché cette extrémité lâche. Je pense que la correction de ce bogue conduirait en fait à un code plus simple - je pourrais essayer de le faire quand j'ai le temps (ha!)
Bennett McElwee
Cool. Oui, si vous supprimez les attr. $ Observez que cela fonctionnera comme prévu. Je collerais ma version ici mais elle ne formatera pas dans les commentaires et est pratiquement identique à la partie observation.
toxaq
@toxaq J'ai édité le code maintenant. Je pense que j'avais adapté le code d'une autre directive, c'est pourquoi l'inapproprié attrs.$observeétait là. Merci pour vos suggestions.
Bennett McElwee
Était sur le point de le suggérer lors de la lecture des réponses suggérées. Propre et réutilisable. +1
Loir
4

N'oubliez pas que si vous utilisez ng-click pour le routage, vous ne pourrez pas cliquer avec le bouton droit sur l'élément et choisir «ouvrir dans un nouvel onglet» ou ctrl en cliquant sur le lien. J'essaie d'utiliser ng-href en matière de navigation. ng-click est préférable d'utiliser sur les boutons pour les opérations ou les effets visuels comme l'effondrement. Mais à propos, je ne recommanderais pas. Si vous changez l'itinéraire, vous devrez peut-être changer beaucoup de place dans l'application. Avoir une méthode renvoyant le lien. ex: À propos. Cette méthode que vous placez dans un utilitaire

Jens Alenius
la source
1

J'ai utilisé la ng-clickdirective pour appeler une fonction, tout en demandant route templateUrl, pour décider laquelle <div>doit être showou à l' hideintérieur de la page route templateUrl ou pour différents scénarios.

AngularJS 1.6.9

Voyons un exemple, lorsque dans la page de routage, j'ai besoin de l'ajout <div>ou de la modification <div>, que je contrôle à l'aide des modèles de contrôleur parent $scope.addProductet $scope.editProductbooléen.

RoutingTesting.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Testing</title>
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular-route.min.js"></script>
    <script>
        var app = angular.module("MyApp", ["ngRoute"]);

        app.config(function($routeProvider){
            $routeProvider
                .when("/TestingPage", {
                    templateUrl: "TestingPage.html"
                });
        });

        app.controller("HomeController", function($scope, $location){

            $scope.init = function(){
                $scope.addProduct = false;
                $scope.editProduct = false;
            }

            $scope.productOperation = function(operationType, productId){
                $scope.addProduct = false;
                $scope.editProduct = false;

                if(operationType === "add"){
                    $scope.addProduct = true;
                    console.log("Add productOperation requested...");
                }else if(operationType === "edit"){
                    $scope.editProduct = true;
                    console.log("Edit productOperation requested : " + productId);
                }

                //*************** VERY IMPORTANT NOTE ***************
                //comment this $location.path("..."); line, when using <a> anchor tags,
                //only useful when <a> below given are commented, and using <input> controls
                $location.path("TestingPage");
            };

        });
    </script>
</head>
<body ng-app="MyApp" ng-controller="HomeController">

    <div ng-init="init()">

        <!-- Either use <a>anchor tag or input type=button -->

        <!--<a href="#!TestingPage" ng-click="productOperation('add', -1)">Add Product</a>-->
        <!--<br><br>-->
        <!--<a href="#!TestingPage" ng-click="productOperation('edit', 10)">Edit Product</a>-->

        <input type="button" ng-click="productOperation('add', -1)" value="Add Product"/>
        <br><br>
        <input type="button" ng-click="productOperation('edit', 10)" value="Edit Product"/>
        <pre>addProduct : {{addProduct}}</pre>
        <pre>editProduct : {{editProduct}}</pre>
        <ng-view></ng-view>

    </div>

</body>
</html>

TestingPage.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        .productOperation{
            position:fixed;
            top: 50%;
            left: 50%;
            width:30em;
            height:18em;
            margin-left: -15em; /*set to a negative number 1/2 of your width*/
            margin-top: -9em; /*set to a negative number 1/2 of your height*/
            border: 1px solid #ccc;
            background: yellow;
        }
    </style>
</head>
<body>

<div class="productOperation" >

    <div ng-show="addProduct">
        <h2 >Add Product enabled</h2>
    </div>

    <div ng-show="editProduct">
        <h2>Edit Product enabled</h2>
    </div>

</div>

</body>
</html>

les deux pages - RoutingTesting.html(parent), TestingPage.html(page de routage) sont dans le même répertoire,

J'espère que cela aidera quelqu'un.

ArifMustafa
la source
1

Une autre solution mais sans utiliser ng-click qui fonctionne toujours même pour d'autres balises que <a>:

<tr [routerLink]="['/about']">

De cette façon, vous pouvez également transmettre des paramètres à votre itinéraire: https://stackoverflow.com/a/40045556/838494

(Ceci est mon premier jour avec angulaire. Une rétroaction douce est la bienvenue)

Albert Hendriks
la source
0

Vous pouvez utiliser:

<a ng-href="#/about">About</a>

Si vous voulez une variable dynamique à l'intérieur de href, vous pouvez faire comme ceci:

<a ng-href="{{link + 123}}">Link to 123</a>

lien est une variable de portée angulaire.

Sohail xIN3N
la source
5
Cela ne répond pas à la question OP, qui concerne l'utilisation ng-clickpour changer d'emplacement.
jjmontes du
0

faites-le comme suit dans votre écriture html:

<button ng-click="going()">goto</button>

Et dans votre contrôleur, ajoutez $ state comme suit:

.controller('homeCTRL', function($scope, **$state**) {

$scope.going = function(){

$state.go('your route');

}

})
LucasMugi
la source