¿Cómo / cuándo usar ng-click para llamar a una ruta?

243

Supongamos que está utilizando rutas:

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

Y en su html, desea navegar a la página acerca de cuando se hace clic en un botón. Una forma sería

<a href="#/about">

... pero parece que ng-click sería útil aquí también.

  1. ¿Es correcta esa suposición? ¿Se usará ng-click en lugar de ancla?
  2. Si es así, ¿cómo funcionaría eso? ES DECIR:

<div ng-click="/about">

Robert Christian
fuente
ui-sref Vea esta respuesta: stackoverflow.com/a/21105057/2539811
Vincil Bishop

Respuestas:

430

Las rutas supervisan el $locationservicio y responden a los cambios en la URL (generalmente a través del hash). Para "activar" una ruta, simplemente cambie la URL. La forma más fácil de hacerlo es con etiquetas de anclaje.

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

No se necesita nada más complicado. Sin embargo, si debe hacer esto desde el código, la forma correcta es mediante el uso del $locationservicio:

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

Que, por ejemplo, un botón podría desencadenar:

<button ng-click="go('/home')"></button>
Josh David Miller
fuente
66
Este no funcionó para mí, pero al reemplazar $ location.hash (hash); con $ location.path (hash); funciona. @Sean sugiere esto en otra respuesta, que tiene muchos menos votos por alguna razón.
Por Quested Aronsson
2
@PerQuestedAronsson pathy hashsirven para dos propósitos diferentes, pero dependiendo de las circunstancias puede tener el mismo efecto. Para la mayoría de los casos, para un enrutamiento estricto (especialmente con html5modehabilitado), pathserá la opción canónica. Actualicé la respuesta para reflejar esto.
Josh David Miller
2
@DavidWoods Debería funcionar, pero solo si la ruta base coincide /. Si está sirviendo la aplicación desde /app/index.html, entonces esto no funcionará porque la URL absoluta es /app/next.html. Obviamente también, el servidor debe estar configurado para devolver su index.htmlarchivo cuando se golpea en /next.html. Siéntase libre de publicar un Plunker / Fiddle si quiere que le eche un vistazo.
Josh David Miller
2
Esto es algo muy genérico y útil de hacer. ¿Hay alguna manera de centralizarlo o realmente tenemos que agregar un gométodo a cada controlador? (¿O crear un controlador raíz con un gométodo?)
Bennett McElwee
3
@BennettMcElwee Creo que, con mucho, el mejor enfoque es usar etiquetas de anclaje; la etiqueta del botón no proporciona ningún valor en este caso y es lo que está creando el problema. Dicho esto, fácilmente se podría crear una directiva para hacer esto para usted, por ejemplo: <button click-go="/home">Click</button>. La función de enlace solo sería esta:element.on("click", function () { $location.path(attrs.clickGo); });
Josh David Miller
83

Aquí hay un gran consejo que nadie mencionó. En el controlador en el que se encuentra la función, debe incluir el proveedor de ubicación:

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
fuente
2
¡Genial, gracias! esta respuesta funcionó mejor para mí, porque el método hash agrega los valores en la url (codificado) y el método de ruta me permitió reemplazar la url completa, eso era lo que necesitaba. ¡Gracias!
jfplataroti
8
Esta es la única solución sugerida en esta página que realmente funcionó. No sé por qué otra respuesta tiene muchos más votos que esta ...
Por Quested Aronsson
Estaba intentando esto, pero no funciona. ¿Tengo que agregar también la ubicación al módulo antes de conectarlo al controlador?
Fallenreaper el
Esto funcionó para mí una vez que configuré ng-click en un div en lugar de un <a>.
Steve
33

El uso de un atributo personalizado (implementado con una directiva) es quizás la forma más limpia. Aquí está mi versión, basada en las sugerencias de @Josh y @ 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);
                });
            });
        }
    }
}]);

Tiene algunas características útiles, pero soy nuevo en Angular, por lo que probablemente haya margen de mejora.

Bennett McElwee
fuente
¿No creará esto un evento de clic en el elemento cada vez que cambie el atributo clickLink?
toxaq
@toxaq Definitivamente no es perfecto. Sospecho que cuando el clickLinkatributo cambia, la directiva agregará el nuevo controlador de clics pero dejará el anterior en su lugar. El resultado podría ser un poco caótico. Originalmente escribí esto para usarlo en una situación en la que el clickLinkatributo nunca cambiaría, por lo que nunca até este extremo suelto. Creo que corregir este error en realidad conduciría a un código más simple. Podría intentar hacerlo cuando tenga tiempo (¡ja!)
Bennett McElwee
Frio. Sí, si sacas los atributos. $ Observa que funcionará según lo previsto. Pegaría mi versión aquí, pero no se formateará en los comentarios y es prácticamente idéntica a la parte de observación.
toxaq
@toxaq He editado el código ahora. Creo que había adaptado el código de alguna otra directiva, es por eso que lo inapropiado attrs.$observeestaba allí. Gracias por sus sugerencias
Bennett McElwee
Estaba a punto de sugerir esto cuando leía las respuestas sugeridas. Limpio y reutilizable. +1
Dormouse
4

Recuerde que si usa ng-click para el enrutamiento, no podrá hacer clic con el botón derecho en el elemento y elegir 'abrir en una pestaña nueva' o presionar Ctrl haciendo clic en el enlace. Intento usar ng-href cuando se trata de navegación. ng-click es mejor usar en botones para operaciones o efectos visuales como colapso. Pero no lo recomendaría. Si cambia la ruta, es posible que deba cambiar en muchos lugares de la aplicación. Tener un método que devuelva el enlace. Ej: Acerca de. Este método lo colocas en una utilidad

Jens Alenius
fuente
1

Utilicé la ng-clickdirectiva para llamar a una función, al solicitar route templateUrl, para decidir cuál <div>debe ser showo hidedentro de la página route templateUrl o para diferentes escenarios.

AngularJS 1.6.9

Veamos un ejemplo, cuando estoy en la página de enrutamiento, necesito agregar <div>o editar <div>, lo cual controlo usando los modelos de controlador principal $scope.addProducty $scope.editProductbooleano.

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>

ambas páginas: RoutingTesting.html(padre), TestingPage.html(página de enrutamiento) están en el mismo directorio,

Espero que esto ayude a alguien.

ArifMustafa
fuente
1

Otra solución pero sin usar ng-click que todavía funciona incluso para otras etiquetas que no sean <a>:

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

De esta manera, también puede pasar parámetros a su ruta: https://stackoverflow.com/a/40045556/838494

(Este es mi primer día con angular. Se aceptan comentarios amables)

Albert Hendriks
fuente
0

Puedes usar:

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

Si desea alguna variable dinámica dentro de href , puede hacer lo siguiente:

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

Donde link es variable de alcance angular.

Sohail xIN3N
fuente
55
Esto no responde a la pregunta OP, que se trata de usar ng-clickpara cambiar la ubicación.
jjmontes
0

simplemente hazlo de la siguiente manera en tu escritura html:

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

Y en su controlador, agregue $ state de la siguiente manera:

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

$scope.going = function(){

$state.go('your route');

}

})
LucasMugi
fuente