Wie / wann kann man mit ng-click eine Route aufrufen?

243

Angenommen, Sie verwenden Routen:

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

Und in Ihrem HTML-Code möchten Sie zur Info-Seite navigieren, wenn Sie auf eine Schaltfläche klicken. Ein Weg wäre

<a href="#/about">

... aber es scheint, dass ng-click auch hier nützlich wäre.

  1. Ist diese Annahme richtig? Dieser ng-Klick anstelle des Ankers verwendet werden?
  2. Wenn ja, wie würde das funktionieren? IE:

<div ng-click="/about">

Robert Christian
quelle
ui-sref Siehe diese Antwort: stackoverflow.com/a/21105057/2539811
Vincil Bishop

Antworten:

430

Routen überwachen den $locationDienst und reagieren auf Änderungen der URL (normalerweise über den Hash). Um eine Route zu "aktivieren", ändern Sie einfach die URL. Der einfachste Weg, dies zu tun, ist mit Ankertags.

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

Es wird nichts Komplizierteres benötigt. Wenn Sie dies jedoch über Code tun müssen, verwenden Sie den $locationDienst ordnungsgemäß :

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

Was zum Beispiel eine Schaltfläche auslösen könnte:

<button ng-click="go('/home')"></button>
Josh David Miller
quelle
6
Dieser hat bei mir nicht funktioniert, aber durch Ersetzen von $ location.hash (Hash); mit $ location.path (Hash); Es klappt. Dies wird von @sean in einer anderen Antwort vorgeschlagen, die aus irgendeinem Grund viel weniger Stimmen hat.
Per Quested Aronsson
2
@PerQuestedAronsson pathund hashdienen zwei verschiedenen Zwecken, können aber je nach Umstand den gleichen Effekt haben. In den meisten Fällen ist für striktes Routing (insbesondere bei html5modeaktiviertem) pathdie kanonische Wahl. Ich habe die Antwort aktualisiert, um dies widerzuspiegeln.
Josh David Miller
2
@ DavidWoods Es sollte funktionieren, aber nur, wenn der Basispfad übereinstimmt /. Wenn Sie die App von bereitstellen /app/index.html, funktioniert dies nicht, da die absolute URL lautet /app/next.html. Natürlich muss auch der Server so eingestellt sein, dass er Ihre index.htmlDatei zurückgibt, wenn er auf getroffen wird /next.html. Fühlen Sie sich frei, einen Plunker / eine Geige zu posten, wenn Sie möchten, dass ich einen Blick darauf werfen kann.
Josh David Miller
2
Dies ist eine sehr allgemeine und nützliche Sache. Gibt es eine Möglichkeit, es zu zentralisieren, oder müssen wir wirklich gojedem Controller eine Methode hinzufügen ? (Oder erstellen Sie einen Root-Controller mit einer goMethode?)
Bennett McElwee
3
@BennettMcElwee Ich denke bei weitem der beste Ansatz ist, nur Ankertags zu verwenden; Das Schaltflächen-Tag liefert in diesem Fall keinen Wert und ist das, was das Problem verursacht. Das heißt, Sie könnten leicht eine Anweisung erstellen, um dies für Sie zu tun, z <button click-go="/home">Click</button>. Die Link-Funktion wäre nur diese:element.on("click", function () { $location.path(attrs.clickGo); });
Josh David Miller
83

Hier ist ein großartiger Tipp, den niemand erwähnt hat. In der Steuerung, in der sich die Funktion befindet, müssen Sie den Standortanbieter angeben:

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
quelle
2
Cool, danke! Diese Antwort funktionierte besser für mich, da die Hash-Methode die Werte an die URL anfügt (codiert) und die Pfadmethode mich die vollständige URL ersetzen lässt, das war es, was ich brauchte. Vielen Dank!
jfplataroti
8
Dies ist die einzige vorgeschlagene Lösung auf dieser Seite, die tatsächlich funktioniert hat. Sie wissen nicht, warum eine andere Antwort viel mehr Stimmen hat als diese ..?
Per Quested Aronsson
Ich habe es versucht, aber es funktioniert nicht. Muss ich dem Modul auch einen Speicherort hinzufügen, bevor ich es an die Steuerung anschließe?
Fallenreaper
Dies funktionierte für mich, nachdem ich ng-click auf ein div anstatt auf ein <a> gesetzt hatte.
Steve
33

Die Verwendung eines benutzerdefinierten Attributs (implementiert mit einer Direktive) ist möglicherweise der sauberste Weg. Hier ist meine Version, basierend auf den Vorschlägen von @Josh und @ 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);
                });
            });
        }
    }
}]);

Es hat einige nützliche Funktionen, aber ich bin neu in Angular, daher gibt es wahrscheinlich Raum für Verbesserungen.

Bennett McElwee
quelle
Wird dadurch nicht jedes Mal ein Klickereignis für das Element erstellt, wenn sich das clickLink-Attribut ändert?
Toxaq
@toxaq Es ist definitiv nicht perfekt. Ich vermute, dass clickLinkdie Direktive den neuen Klick-Handler hinzufügt , wenn sich das Attribut ändert, aber den alten an Ort und Stelle lässt. Das Ergebnis könnte etwas chaotisch sein. Ich habe dies ursprünglich geschrieben, um es in einer Situation zu verwenden, in der sich das clickLinkAttribut niemals ändern würde, also habe ich dieses lose Ende nie gebunden. Ich denke, das Beheben dieses Fehlers würde tatsächlich zu einfacherem Code führen - ich könnte versuchen, es zu tun, wenn ich Zeit habe (ha!)
Bennett McElwee
Cool. Ja, wenn Sie die Attribute herausnehmen. $ Beachten Sie, dass es wie beabsichtigt funktioniert. Ich würde meine Version hier einfügen, aber sie wird nicht in den Kommentaren formatiert und ist praktisch identisch, abgesehen vom Beobachtungsteil.
Toxaq
@toxaq Ich habe den Code jetzt bearbeitet. Ich glaube, ich hatte den Code aus einer anderen Richtlinie übernommen, deshalb war das Unangemessene attrs.$observeda. Vielen Dank für Ihre Vorschläge.
Bennett McElwee
Wollte dies beim Lesen der vorgeschlagenen Antworten vorschlagen. Sauber und wiederverwendbar. +1
Siebenschläfer
4

Denken Sie daran, dass Sie bei Verwendung von ng-click für das Routing nicht mit der rechten Maustaste auf das Element klicken und "In neuem Tab öffnen" auswählen oder bei gedrückter Strg-Taste auf den Link klicken können. Ich versuche, ng-href zu verwenden, wenn es um Navigation geht. ng-click ist besser für Schaltflächen für Operationen oder visuelle Effekte wie das Reduzieren. Aber über würde ich nicht empfehlen. Wenn Sie die Route ändern, müssen Sie möglicherweise viele in der Anwendung platzierte ändern. Lassen Sie den Link von einer Methode zurückgeben. Beispiel: Über. Diese Methode platzieren Sie in einem Dienstprogramm

Jens Alenius
quelle
1

Ich verwendete ng-clickRichtlinie eine Funktion aufzurufen, während Route templateUrl anfordert, zu entscheiden , welche <div>zu sein hat showoder hideinnerhalb Route templateUrl Seite oder für verschiedene Szenarien.

AngularJS 1.6.9

Sehen wir uns ein Beispiel an, wenn ich auf der Routing-Seite entweder das Hinzufügen <div>oder das Bearbeiten benötige <div>, das ich mithilfe der übergeordneten Controller-Modelle $scope.addProductund des $scope.editProductBooleschen Werts steuere.

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>

beide Seiten - RoutingTesting.html(übergeordnet), TestingPage.html(Routing-Seite) befinden sich im selben Verzeichnis,

Hoffe das wird jemandem helfen.

ArifMustafa
quelle
1

Eine andere Lösung, aber ohne Verwendung von ng-click, die auch für andere Tags als funktioniert <a>:

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

Auf diese Weise können Sie auch Parameter an Ihre Route übergeben: https://stackoverflow.com/a/40045556/838494

(Dies ist mein erster Tag mit eckigen. Sanftes Feedback ist willkommen)

Albert Hendriks
quelle
0

Sie können verwenden:

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

Wenn Sie eine dynamische Variable in href möchten , können Sie dies folgendermaßen tun:

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

Wobei Link Angular Scope Variable ist.

Sohail xIN3N
quelle
5
Dies beantwortet nicht die OP-Frage, mit ng-clickder der Standort geändert werden soll.
Jjmontes
0

Machen Sie es einfach wie folgt in Ihrem HTML-Text:

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

Fügen Sie in Ihrem Controller $ state wie folgt hinzu:

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

$scope.going = function(){

$state.go('your route');

}

})
LucasMugi
quelle