AngularJS: Comment changer de vue depuis une fonction de contrôleur?


237

J'essaie d'utiliser la fonction ng-click d'AngularJS pour changer de vue. Comment pourrais-je procéder avec le code ci-dessous?

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?
        }
    }

Réponses:


314

Afin de basculer entre différentes vues, vous pouvez modifier directement le window.location (en utilisant le service $ location!) Dans le fichier 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
        }
    }

et configurez le routeur pour basculer vers différents partiels en fonction de l'emplacement (comme indiqué ici https://github.com/angular/angular-seed/blob/master/app/app.js ). Cela aurait l'avantage de l'histoire ainsi que l'utilisation de ng-view.

Alternativement, vous utilisez ng-include avec différents partiels, puis utilisez un ng-switch comme indiqué ici ( https://github.com/ganarajpr/Angular-UI-Components/blob/master/index.html )


Je reçois une erreur indiquant que le hachage n'est pas fonction de $ location.
The_Brink

Je ne vois pas le hachage comme faisant partie de l'objet $ location, mais il y a une variable de hachage $$, donc ça ne fonctionne pas.
The_Brink

OK, j'ai découvert comment le faire. $ location.path (vue); ( docs.angularjs.org/guide/dev_guide.services.$location )
The_Brink

@The_Brink Merci pour la modification. Je ne sais pas pourquoi il a été rejeté. J'ai apporté des modifications pour refléter ce que j'essayais de dire.
ganaraj

2
La meilleure chose à faire est de créer un lien normal. <a href="https://stackoverflow.com/edit">Edit</a> Angular s'assurera que le clic ne crée pas de rechargement de page. Ce comportement peut être modifié afin qu'il déclenche un rechargement si cela est souhaité.
Anthony Martin

38

La réponse fournie est absolument correcte, mais je voulais développer pour tous les futurs visiteurs qui voudraient le faire un peu plus dynamiquement -

Dans la vue -

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

Dans le contrôleur -

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

Même concept de base que la réponse acceptée, en y ajoutant simplement du contenu dynamique pour l'améliorer un peu. Si la réponse acceptée veut l'ajouter, je supprimerai ma réponse.


8
un nitpick total, mais pour info, a urlest en fait l' adresse Web complète , y compris le protocole (http: //) et tout. Comme l'indique $location.path()votre variable, il vaut mieux le décrire comme un path.
Zach Lysobey

Mais cela nécessite un $ rootScope. $ Digest (); ou $ scope. $ apply (); afin de le faire bouger sans tarder.
Raz

23

J'ai un exemple qui fonctionne.

Voici à quoi ressemble mon doc:

<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>

Voici à quoi ressemble mon partiel:

<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>

Voici à quoi ressemble mon Ctrl:

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

l'application est mon module:

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

J'espère que cela vous sera utile!


12

La méthode utilisée pour toutes les réponses précédentes à cette question suggère de changer l'URL qui n'est pas nécessaire, et je pense que les lecteurs devraient être conscients d'une solution alternative. J'utilise ui-router et $ stateProvider pour associer une valeur d'état à un templateUrl qui pointe vers le fichier html pour votre vue. Ensuite, il suffit d'injecter l'état $ dans votre contrôleur et d'appeler $ state.go ('state-value') pour mettre à jour votre vue.

Quelle est la différence entre angular-route et angular-ui-router?


5

Il y a deux façons de procéder:

Si vous utilisez ui-router ou $stateProvider, faites-le comme:

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

si vous utilisez un routeur angulaire ou $routeProviderfaites-le comme:

$location.path('routeName'); //similarily include $location service in your controller

Une chose qui m'a fait trébucher était d'utiliser le nom de l'itinéraire au lieu du nom de l'état ... c'est-à-dire qu'il devrait être "principal" au lieu de "/ principal"
Ben Schmidt

3

Sans faire une refonte complète de l'environnement de routage par défaut (# / ViewName), j'ai pu faire une légère modification de l'astuce de Cody et le faire fonctionner correctement.

le controlle

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

la vue

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

Ce qui m'a amené à cette solution, c'est lorsque j'essayais d'intégrer un widget Kendo Mobile UI dans un environnement angulaire, je perdais le contexte de mon contrôleur et le comportement de la balise d'ancrage régulière était également détourné. J'ai rétabli mon contexte à partir du widget Kendo et j'avais besoin d'utiliser une méthode pour naviguer ... cela a fonctionné.

Merci pour les messages précédents!


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'); 

J'espère que ceci vous aidera


2

Cette petite fonction m'a bien servi:

    //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;
        }


    };

Vous n'avez pas besoin du chemin complet, juste la vue vers laquelle vous passez

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.