Jak / kiedy używać ng-kliknij, aby zadzwonić na trasę?

243

Załóżmy, że korzystasz z tras:

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

A w html chcesz przejść do strony about po kliknięciu przycisku. Jednym ze sposobów byłoby

<a href="#/about">

... ale wydaje się, że kliknięcie ng również byłoby tu przydatne.

  1. Czy to założenie jest prawidłowe? Czy zamiast zakotwiczenia można użyć kliknięcia ng?
  2. Jeśli tak, jak to by działało? TO ZNACZY:

<div ng-click="/about">

Robert Christian
źródło
ui-sref Zobacz tę odpowiedź: stackoverflow.com/a/21105057/2539811
Vincil Bishop

Odpowiedzi:

430

Trasy monitorują $locationusługę i reagują na zmiany adresu URL (zazwyczaj za pomocą skrótu). Aby „aktywować” trasę, wystarczy zmienić adres URL. Najłatwiej to zrobić za pomocą tagów zakotwiczenia.

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

Nic bardziej skomplikowanego nie jest potrzebne. Jeśli jednak musisz to zrobić z kodu, właściwym sposobem jest skorzystanie z $locationusługi:

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

Który na przykład przycisk może uruchomić:

<button ng-click="go('/home')"></button>
Josh David Miller
źródło
6
Ten nie działał dla mnie, ale przez zastąpienie $ location.hash (hash); z $ location.path (skrót); to działa. Sugeruje to @sean w innej odpowiedzi, która z jakiegoś powodu ma znacznie mniej głosów.
Per Quested Aronsson
2
@PerQuestedAronsson pathi hashsłużą dwóm różnym celom, ale w zależności od okoliczności mogą mieć ten sam efekt. W większości przypadków wybór ścisły będzie html5modemożliwy w przypadku ścisłego routingu (zwłaszcza z włączoną funkcją) path. Zaktualizowałem odpowiedź, aby to odzwierciedlić.
Josh David Miller
2
@DavidWoods Powinno działać, ale tylko jeśli ścieżka podstawowa jest zgodna /. Jeśli podajesz aplikację z /app/index.html, to nie zadziała, ponieważ jest to bezwzględny adres URL /app/next.html. Oczywiście, serwer musi być ustawiony tak, aby zwracał twój index.htmlplik po trafieniu /next.html. Jeśli chcesz, żebym rzucił okiem, możesz opublikować Plunker / Fiddle.
Josh David Miller,
2
Jest to bardzo ogólna i przydatna rzecz do zrobienia. Czy istnieje sposób na scentralizowanie go, czy naprawdę musimy dodać gometodę do każdego kontrolera? (Lub utworzyć kontroler root za pomocą gometody?)
Bennett McElwee
3
@BennettMcElwee Myślę, że zdecydowanie najlepszym rozwiązaniem jest po prostu użycie tagów kotwicy; tag przycisku nie podaje w tym przypadku żadnej wartości i jest przyczyną problemu. To powiedziawszy, możesz łatwo stworzyć dyrektywę, aby zrobić to za Ciebie, np <button click-go="/home">Click</button>. : . Funkcja łączenia byłaby tylko taka:element.on("click", function () { $location.path(attrs.clickGo); });
Josh David Miller
83

Oto świetna wskazówka, o której nikt nie wspomniał. W kontrolerze, w którym znajduje się ta funkcja, musisz dołączyć dostawcę lokalizacji:

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
źródło
2
fajne dzięki! ta odpowiedź działała dla mnie lepiej, ponieważ metoda mieszania dołącza wartości do adresu URL (zakodowanego), a metoda ścieżki pozwala mi zastąpić pełny adres URL, tego właśnie potrzebowałem. dzięki!
jfplataroti
8
To jedyne sugerowane rozwiązanie na tej stronie, które faktycznie działało. Nie wiem, dlaczego inna odpowiedź ma o wiele więcej głosów niż ta ..?
Per Quested Aronsson
Próbowałem tego, ale to nie działa. Czy muszę również dodać lokalizację do modułu przed podłączeniem go do kontrolera?
Fallenreaper
To działało dla mnie, kiedy ustawiłem ng-kliknięcie na div, a nie na <a>.
Steve
33

Użycie niestandardowego atrybutu (zaimplementowanego w dyrektywie) jest być może najczystszym sposobem. Oto moja wersja, oparta na sugestiach @Josh i @ 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);
                });
            });
        }
    }
}]);

Ma kilka przydatnych funkcji, ale jestem nowy w Angular, więc prawdopodobnie jest miejsce na ulepszenia.

Bennett McElwee
źródło
Czy nie utworzy to zdarzenia kliknięcia na elemencie przy każdej zmianie atrybutu clickLink?
toxaq
@toxaq To zdecydowanie nie jest idealne. Podejrzewam, że gdy clickLinkzmieni się atrybut, dyrektywa doda nowy moduł obsługi kliknięć, ale pozostawi stary na miejscu. Rezultat może być nieco chaotyczny. Pierwotnie napisałem to do użycia w sytuacji, gdy clickLinkatrybut nigdy się nie zmieni, więc nigdy nie związałem tego luźnego końca. Myślę, że naprawienie tego błędu doprowadziłoby do uproszczenia kodu - mógłbym spróbować to zrobić, kiedy będę miał czas (ha!)
Bennett McElwee
Chłodny. Tak, jeśli usuniesz attrs. $ Obserwuj, że będzie działać zgodnie z przeznaczeniem. Wkleiłbym tutaj swoją wersję, ale nie sformatuje się ona w komentarzach i jest praktycznie identyczna z paskiem obserwowanej części.
toxaq
@toxaq Edytowałem kod teraz. Myślę, że dostosowałem kod z jakiejś innej dyrektywy, dlatego niewłaściwe attrs.$observebyło. Dziękuję za twoje sugestie.
Bennett McElwee,
Już miałem to zasugerować, czytając sugerowane odpowiedzi. Czysty i wielokrotnego użytku. +1
Koszatka
4

Pamiętaj, że jeśli używasz ng-click do routingu, nie będziesz w stanie kliknąć elementu prawym przyciskiem myszy i wybrać „otwórz w nowej karcie” lub kliknij z wciśniętym klawiszem Ctrl. Staram się używać ng-href, jeśli chodzi o nawigację. ng-click lepiej jest używać na przyciskach do operacji lub efektów wizualnych, takich jak zwinięcie. Ale o nie polecam. Jeśli zmienisz trasę, być może będziesz musiał zmienić wiele z umieszczonych w aplikacji. Poproś o metodę zwracającą link. np .: o. Tę metodę umieszczasz w narzędziu

Jens Alenius
źródło
1

Użyłem ng-clickdyrektywy, aby wywołać funkcję, podczas żądania trasy templateUrl, aby zdecydować, która <div>ma być, showlub hidewewnątrz strony templateUrl trasy lub dla różnych scenariuszy.

AngularJS 1.6.9

Zobaczmy przykład, gdy na stronie routingu potrzebuję dodawania <div>lub edycji <div>, które kontroluję za pomocą modeli kontrolera nadrzędnego $scope.addProducti wartości $scope.editProductlogicznej.

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>

obie strony - RoutingTesting.html(rodzic), TestingPage.html(strona routingu) znajdują się w tym samym katalogu,

Mam nadzieję, że to komuś pomoże.

ArifMustafa
źródło
1

Inne rozwiązanie, ale bez użycia ng-click, które nadal działa nawet w przypadku innych tagów niż <a>:

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

W ten sposób możesz również przekazać parametry do trasy: https://stackoverflow.com/a/40045556/838494

(To mój pierwszy dzień z angularem. Mile widziane są delikatne opinie)

Albert Hendriks
źródło
0

Możesz użyć:

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

Jeśli chcesz jakieś dynamiczne zmienne wewnątrz href, możesz to zrobić w ten sposób:

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

Gdzie link jest zmienną zakresu kątowego.

Sohail xIN3N
źródło
5
To nie odpowiada na pytanie OP, które dotyczy ng-clickzmiany lokalizacji.
jjmontes,
0

po prostu zrób to w następujący sposób w swoim pliku HTML:

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

I w kontrolerze dodaj $ state w następujący sposób:

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

$scope.going = function(){

$state.go('your route');

}

})
LucasMugi
źródło