AngularJS: Como alternar visualizações de uma função do controlador?

237

Estou tentando usar o recurso ng-click do AngularJS para alternar visualizações. Como eu faria isso com o código abaixo?

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?
        }
    }
À beira
fonte

Respostas:

314

Para alternar entre diferentes visualizações, você pode alterar diretamente o window.location (usando o serviço $ location!) No arquivo 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
        }
    }

e configure o roteador para alternar para parciais diferentes com base no local (como mostrado aqui https://github.com/angular/angular-seed/blob/master/app/app.js ). Isso traria benefícios à história e ao uso da ng-view.

Como alternativa, você usa ng-include com diferentes parciais e, em seguida, usa um ng-switch, como mostrado aqui ( https://github.com/ganarajpr/Angular-UI-Components/blob/master/index.html )

ganaraj
fonte
Estou recebendo um erro que diz que o hash não é função de $ location.
The_Brink
Não vejo o hash como parte do objeto $ location, mas há uma variável $$ hash, portanto é isso e, se for, não funciona.
The_Brink
OK, eu descobri como fazê-lo. $ location.path (exibir); ( docs.angularjs.org/guide/dev_guide.services.$location )
The_Brink
@The_Brink Obrigado pela edição. Não sei por que foi rejeitado. Fiz alterações para refletir o que estava tentando dizer.
11555 Ganhoj
2
A melhor coisa a fazer é apenas criar um link normal. <a href="https://stackoverflow.com/edit">Edit</a> Angular garantirá que o clique não crie um recarregamento de página. Esse comportamento pode ser modificado para ativar uma recarga, se desejado.
Anthony Martin
38

A resposta fornecida está absolutamente correta, mas eu queria expandir para futuros visitantes que queiram fazê-lo um pouco mais dinamicamente -

Na visão -

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

No controlador -

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

O mesmo conceito básico da resposta aceita, apenas adicionando algum conteúdo dinâmico a ele para melhorar um pouco. Se a resposta aceita quiser adicionar isso, excluirei minha resposta.

PW Kad
fonte
8
um total nitpick, mas, para sua informação, a urlé realmente o endereço da web completo , incluindo o protocolo (http: //) e tudo mais. Como está implícito na $location.path()sua variável, é melhor descrito como a path.
Zach Lysobey
Mas isso requer um $ rootScope. $ Digest (); ou $ scope. $ apply (); para fazê-lo se mover sem demora.
Raz
23

Eu tenho um exemplo trabalhando.

Aqui está a aparência do meu 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>

Aqui está a aparência da minha 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>

Aqui está a aparência do meu Ctrl:

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

app é meu módulo:

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

Espero que isso seja útil!

Cody
fonte
12

O método usado para todas as respostas anteriores a essa pergunta sugere alterar o URL que não é necessário, e acho que os leitores devem estar cientes de uma solução alternativa. Eu uso o ui-router e o $ stateProvider para associar um valor de estado a um templateUrl que aponta para o arquivo html da sua exibição. Depois, basta injetar o $ state no seu controlador e chamar $ state.go ('state-value') para atualizar sua visualização.

Qual é a diferença entre rota angular e angular-ui-router?

Gavin Palmer
fonte
5

Existem duas maneiras para isso:

Se você estiver usando o ui-router ou $stateProvider, faça-o como:

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

se você estiver usando roteador angular ou $routeProvider, faça-o como:

$location.path('routeName'); //similarily include $location service in your controller
Sukhminder Parmar
fonte
Em coisa que me tropeçar estava usando o nome da rota, em vez do nome do estado ... ou seja, ele deve ser "principal" em vez de "/ main"
Ben Schmidt
3

Sem fazer uma reformulação completa do ambiente de roteamento padrão (# / ViewName), pude fazer uma ligeira modificação na dica de Cody e fazer com que funcionasse muito bem.

o controlador

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

a vista

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

O que me levou a essa solução foi que, quando estava tentando integrar um widget de interface do usuário do Kendo Mobile em um ambiente angular, estava perdendo o contexto do meu controlador e o comportamento da tag de âncora regular também estava sendo invadido. Restabeleci meu contexto a partir do widget Kendo e precisava usar um método para navegar ... isso funcionou.

Obrigado pelas postagens anteriores!

beauXjames
fonte
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 isso ajude você

Vaishali Tekale
fonte
2

Essa pequena função me serviu bem:

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


    };

Você não precisa do caminho completo, apenas da visualização para a qual está mudando

Shawn Dotey
fonte