AngularJS: ¿Cómo cambio las vistas desde una función de controlador?

237

Estoy tratando de usar la función ng-click de AngularJS para cambiar de vista. ¿Cómo haría para hacer esto con el siguiente código?

index.html

 <div ng-controller="Cntrl">
        <div ng-click="someFunction()">
            click me
        <div>
    <div>

controller.js

  function Cntrl ($scope) {
        $scope.someFunction = function(){
            //code to change view?
        }
    }
Al borde
fuente

Respuestas:

314

Para cambiar entre diferentes vistas, puede cambiar directamente la ubicación de la ventana (¡usando el servicio $ location!) En el archivo index.html

<div ng-controller="Cntrl">
        <div ng-click="changeView('edit')">
            edit
        </div>
        <div ng-click="changeView('preview')">
            preview
        </div>
</div>

Controller.js

function Cntrl ($scope,$location) {
        $scope.changeView = function(view){
            $location.path(view); // path not hash
        }
    }

y configure el enrutador para cambiar a diferentes parciales según la ubicación (como se muestra aquí https://github.com/angular/angular-seed/blob/master/app/app.js ). Esto tendría el beneficio de la historia, así como el uso de ng-view.

Alternativamente, usa ng-include con diferentes parciales y luego usa un ng-switch como se muestra aquí ( https://github.com/ganarajpr/Angular-UI-Components/blob/master/index.html )

ganaraj
fuente
Recibo un error que dice que el hash no es función de $ location.
The_Brink
No veo el hash como parte del objeto $ location, pero hay una variable $$ hash, por lo que es así y, de ser así, no funciona.
The_Brink
OK, descubrí cómo hacerlo. $ location.path (ver); ( docs.angularjs.org/guide/dev_guide.services.$location )
The_Brink
@The_Brink Gracias por la edición. No sé por qué fue rechazado. Hice cambios para reflejar lo que intentaba decir.
ganaraj
2
Lo mejor que puedes hacer es hacer un enlace normal. <a href="https://stackoverflow.com/edit">Edit</a> Angular se asegurará de que el clic no cree una recarga de página. Este comportamiento se puede modificar para que active una recarga si se desea.
Anthony Martin
38

La respuesta proporcionada es absolutamente correcta, pero quería expandirme para cualquier visitante futuro que quiera hacerlo de manera más dinámica:

En la vista

<div ng-repeat="person in persons">
    <div ng-click="changeView(person)">
        Go to edit
    <div>
<div>

En el controlador

$scope.changeView = function(person){
    var earl = '/editperson/' + person.id;
    $location.path(earl);
}

El mismo concepto básico que la respuesta aceptada, solo agregando contenido dinámico para mejorar un poco. Si la respuesta aceptada quiere agregar esto, eliminaré mi respuesta.

PW Kad
fuente
8
un punto crítico total, pero para su información, a urles en realidad la dirección web completa , incluido el protocolo (http: //) y todo. Como lo implica $location.path()su variable, se describe mejor como a path.
Zach Lysobey
Pero requiere un $ rootScope. $ Digest (); o $ scope. $ apply (); para que se mueva sin demora.
Raz
23

Tengo un ejemplo funcionando.

Así es como se ve mi documento:

<html>
<head>
    <link rel="stylesheet" href="css/main.css">
    <script src="//ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>
    <script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.0.3/angular.min.js"></script>
    <script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.0.3/angular-resource.min.js"></script>
    <script src="js/app.js"></script>
    <script src="controllers/ctrls.js"></script>
</head>
<body ng-app="app">
    <div id="contnr">
        <ng-view></ng-view>
    </div>
</body>
</html>

Así es como se ve mi parcial:

<div id="welcome" ng-controller="Index">
    <b>Welcome! Please Login!</b>
    <form ng-submit="auth()">
        <input class="input login username" type="text" placeholder="username" /><br>
        <input class="input login password" type="password" placeholder="password" /><br>
        <input class="input login submit" type="submit" placeholder="login!" />
    </form>
</div>

Así es como se ve mi Ctrl:

app.controller('Index', function($scope, $routeParams, $location){
    $scope.auth = function(){
        $location.url('/map');
    };
});

la aplicación es mi módulo:

var app = angular.module('app', ['ngResource']).config(function($routeProvider)...

Espero que esto sea útil!

Cody
fuente
12

El método utilizado para todas las respuestas anteriores a esta pregunta sugiere cambiar la URL, lo que no es necesario, y creo que los lectores deberían conocer una solución alternativa. Uso ui-router y $ stateProvider para asociar un valor de estado con una templateUrl que apunta al archivo html para su vista. Entonces es solo una cuestión de inyectar el $ state en su controlador y llamar a $ state.go ('state-value') para actualizar su vista.

¿Cuál es la diferencia entre angular-route y angular-ui-router?

Gavin Palmer
fuente
5

Hay dos formas para esto:

Si está utilizando ui-router o $stateProvider, hágalo como:

$state.go('stateName'); //remember to add $state service in the controller

si está utilizando un enrutador angular o $routeProviderhágalo como:

$location.path('routeName'); //similarily include $location service in your controller
Sukhminder Parmar
fuente
Lo que me hizo tropezar fue usar el nombre de la ruta en lugar del nombre del estado ... es decir, debería ser "main" en lugar de "/ main"
Ben Schmidt
3

Sin hacer una renovación completa del entorno de enrutamiento predeterminado (# / ViewName), pude hacer una ligera modificación de la sugerencia de Cody y conseguí que funcionara de maravilla.

el controlador

.controller('GeneralCtrl', ['$route', '$routeParams', '$location',
        function($route, $routeParams, $location) {
            ...
            this.goToView = function(viewName){
                $location.url('/' + viewName);
            }
        }]
    );

la vista

...
<li ng-click="general.goToView('Home')">HOME</li>
...

Lo que me llevó a esta solución fue que cuando intentaba integrar un widget Kendo Mobile UI en un entorno angular, estaba perdiendo el contexto de mi controlador y el comportamiento de la etiqueta de anclaje normal también estaba siendo secuestrado. Restablecí mi contexto desde el widget de Kendo y necesitaba usar un método para navegar ... esto funcionó.

Gracias por las publicaciones anteriores!

beauXjames
fuente
2
Firstly you have to create state in app.js as below

.state('login', {
      url: '/',
      templateUrl: 'views/login.html',
      controller: 'LoginCtrl'
    })

and use below code in controller

 $location.path('login'); 

Espero que esto te ayudará

Vaishali Tekale
fuente
2

Esta pequeña función me ha servido bien:

    //goto view:
    //useage -  $scope.gotoView("your/path/here", boolean_open_in_new_window)
    $scope.gotoView = function (st_view, is_newWindow)
    {

        console.log('going to view: ' + '#/' + st_view, $window.location);
        if (is_newWindow)
        {
            $window.open($window.location.origin + $window.location.pathname + '' + '#/' + st_view, '_blank');
        }
        else
        {
            $window.location.hash = '#/' + st_view;
        }


    };

No necesita la ruta completa, solo la vista a la que está cambiando

Shawn Dotey
fuente