Як / коли використовувати ng-клік для виклику маршруту?


243

Припустимо, ви використовуєте маршрути:

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

І у вашому html ви хочете перейти на сторінку про інформацію, коли натиснути кнопку. Один із способів був би

<a href="#/about">

... але, здається, натискання кнопки "ng" також було б корисно і тут.

  1. Чи правильно це припущення? Що натискання ng буде використано замість якоря?
  2. Якщо так, то як би це працювало? IE:

<div ng-click="/about">



щ-sref Дивіться цей відповідь: stackoverflow.com/a/21105057/2539811
Vincil Bishop

Відповіді:


430

Маршрути відстежують $locationслужбу та реагують на зміни URL-адреси (як правило, через хеш). Щоб "активувати" маршрут, ви просто зміните URL-адресу. Найпростіший спосіб зробити це з допомогою якорних тегів.

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

Нічого складнішого не потрібно. Якщо, однак, це потрібно зробити з коду, правильним способом є використання $locationсервісу:

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

Що, наприклад, може запустити кнопку:

<button ng-click="go('/home')"></button>

6
Цей не працював для мене, але замінивши $ location.hash (хеш); з $ location.path (хеш); це працює. Про це пропонує @sean в іншій відповіді, яка чомусь має набагато менше голосів.
Запитаний Аронсон

2
@PerQuestedAronsson pathі hashслужить двом різним цілям, але залежно від обставин може мати однаковий ефект. У більшості випадків канонічним вибором стане сувора маршрутизація (особливо з html5modeвключеною) path. Я оновив відповідь, щоб це відобразити.
Джош Девід Міллер

2
@DavidWoods Це має працювати, але лише у тому випадку, якщо базовий шлях відповідає /. Якщо ви обслуговуєте додаток /app/index.html, це не працюватиме, оскільки абсолютна URL-адреса є /app/next.html. Очевидно також, що сервер повинен бути налаштований для повернення вашого index.htmlфайлу при натисканні на /next.html. Якщо ви хочете, щоб я подивився, не соромтеся опублікувати Плункер / Скрипку.
Джош Девід Міллер

2
Це дуже загальна та корисна річ. Чи є спосіб її централізувати, чи нам дійсно потрібно додати goметод до кожного контролера? (Або створити кореневий контролер goметодом?)
Bennett McElwee

3
@BennettMcElwee Я думаю, що на сьогоднішній день найкращим підходом є просто використання якорних тегів; тег кнопок не дає значення в цьому випадку і є тим, що створює проблему. Тим НЕ менше, ви можете легко створити директиву , щоб зробити це для вас, наприклад: <button click-go="/home">Click</button>. Функція зв’язку була б лише такою:element.on("click", function () { $location.path(attrs.clickGo); });
Джош Девід Міллер

83

Ось чудова порада, яку ніхто не згадував. У контролері, в якому знаходиться функція, потрібно включити постачальника розташування:

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>

2
класно дякую! ця відповідь працювала для мене краще, оскільки хеш-метод додає значення до URL-адреси (закодований), а метод шляху дозволив мені замінити повний URL-адрес, саме це мені і було потрібно. Дякую!
jfplataroti

8
Це єдине запропоноване рішення на цій сторінці, яке фактично працювало. Не знаєте, чому інша відповідь має набагато більше голосів, ніж ця ..?
Запитаний Аронсон

Я намагався це, але це не працює. Чи потрібно додати місце розташування до модуля також перед тим, як приєднати його до контролера?
Fallenreaper

Це спрацювало для мене, як тільки я встановив ng-натискання на div, а не <a>.
Стів

33

Використання спеціального атрибута (реалізованого за допомогою директиви) - чи не найчистіший спосіб. Ось моя версія, заснована на пропозиціях @Josh та @ 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);
                });
            });
        }
    }
}]);

Він має деякі корисні функції, але я новачок у Angular, тому, можливо, є можливість для вдосконалення.


Чи не створить це подія клацання на елементі щоразу, коли атрибут clickLink змінюється?
toxaq

@toxaq Це точно не ідеально. Я підозрюю, що коли clickLinkатрибут зміниться, директива додасть новий обробник кліків, але залишить старий на місці. Результат може бути трохи хаотичним. Я спочатку написав це для використання в ситуації, коли clickLinkатрибут ніколи не змінився, тому я ніколи не зав'язував цей вільний кінець. Я думаю, що виправлення цієї помилки насправді призведе до більш простого коду - я б спробував це зробити, коли
встигну

Класно. Так, якщо ви виймете attrs. $ Спостерігайте, це працюватиме за призначенням. Я б вставив сюди свою версію, але вона не буде форматуватися в коментарях і є практично однаковою смугою частини спостереження.
toxaq

@toxaq Я редагував код зараз. Я думаю, що я адаптував код із якоїсь іншої директиви, тому невідповідний attrs.$observeбув. Дякуємо за ваші пропозиції.
Bennett McElwee

Збирався запропонувати це, читаючи запропоновані відповіді. Чисті та багаторазові. +1
Dormouse

4

Пам’ятайте, що якщо ви використовуєте ng-click для маршрутизації, ви не зможете клацнути правою кнопкою миші елемент та оберіть «відкрити в новій вкладці» або натиснути посилання. Я намагаюся використовувати ng-href, коли йдеться про навігацію. ng-клацання краще використовувати на кнопках для операцій або візуальних ефектів, таких як колапс. Але про я б не рекомендував. Якщо ви зміните маршрут, можливо, вам доведеться змінити багато місця, розміщеного в програмі. Мати метод повернення посилання. колишній: Про. Цей метод ви розміщуєте в утиліті


1

Я використовував ng-clickдирективу для виклику функції, запитуючи маршрут templateUrl, щоб вирішити, яка <div>повинна бути сторінка маршруту showабо hideвсередині сторінки templateUrl або для різних сценаріїв.

AngularJS 1.6.9

Подивимось приклад, коли на сторінці маршрутизації мені потрібно або додати, <div>або змінити <div>, якими я керую за допомогою батьківських моделей контролера $scope.addProductта $scope.editProductбулевих.

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>

обидві сторінки - RoutingTesting.html(батьківська), TestingPage.html(сторінка маршрутизації) знаходяться в одному каталозі,

Сподіваюся, що це комусь допоможе.


1

Ще одне рішення, але без використання ng-click, яке все ще працює навіть для інших тегів, ніж <a>:

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

Таким чином ви також можете передати параметри до свого маршруту: https://stackoverflow.com/a/40045556/838494

(Це мій перший день з кутовим. Ласкавий відгук вітається)


0

Ви можете використовувати:

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

Якщо ви хочете отримати якусь динамічну змінну всередині href, ви можете зробити так:

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

Де посилання - кутова змінна область.


5
Це не відповідає на питання ОП, яке стосується використання ng-clickмісця зміни.
jjmontes

0

просто зробіть це так, як у вашому html пишіть:

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

А у своєму контролері додайте $ state так:

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

$scope.going = function(){

$state.go('your route');

}

})
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.