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?
        }
    }
The_Brink
la source

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 )

ganaraj
la source
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.

PW Kad
la source
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!

Cody
la source
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?

Gavin Palmer
la source
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
Sukhminder Parmar
la source
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!

beauXjames
la source
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

Vaishali Tekale
la source
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

Shawn Dotey
la source