bootstrap Combatendo o AngularJS executando o controlador duas vezes




angularjs examples (18)

Acabei de resolver o meu, o que foi bastante decepcionante. É um aplicativo híbrido iônico, eu usei ui-roteador v0.2.13. No meu caso, há um epub reader (usando epub.js) que relatava continuamente "nenhum documento encontrado" quando eu navegava para a biblioteca de livros e selecionava qualquer outro livro. Quando eu recarreguei o livro do navegador estava sendo processado perfeitamente, mas quando eu selecionei outro livro tenho o mesmo problema novamente.

Minha resolução foi muito simples. Acabei de remover reload:true de $state.go("app.reader", { fileName: fn, reload: true }); na minha LibraryController

Eu entendo que o AngularJS é executado através de algum código duas vezes, às vezes até mais, como $watch events, verificando constantemente os estados do modelo etc.

No entanto meu código:

function MyController($scope, User, local) {

var $scope.User = local.get(); // Get locally save user data

User.get({ id: $scope.User._id.$oid }, function(user) {
  $scope.User = new User(user);
  local.save($scope.User);
});

//...

É executado duas vezes, inserindo 2 registros no meu banco de dados. Eu ainda estou claramente aprendendo como eu tenho batido minha cabeça contra isso por muito tempo!


Answer #1

Eu acabei de passar por isso, mas a questão era diferente da resposta aceita. Eu estou realmente deixando isso aqui para o meu futuro, para incluir os passos que eu passei para consertá-lo.

  1. Remover declarações de controlador redundantes
  2. Verifique as barras finais nas rotas
  3. Verifique se há ng-ifs
  4. Verifique se há alguma chamada desnecessária para o wrap ng-view (que eu acidentalmente deixei em uma ng-view que estava envolvendo minha ng-view real. Isso resultou em três chamadas para meus controladores.)
  5. Se você está no Rails, você deve remover a gem do turbolinks do seu arquivo application.js . Eu perdi um dia inteiro para descobrir isso. Encontrei resposta here .
  6. Inicializando o aplicativo duas vezes com o ng-app e com o bootstrap. Combatendo o AngularJS executando o controlador duas vezes
  7. Ao usar $ compile no elemento inteiro em 'link'-function da diretiva que também tem seu próprio controlador definido e usa callbacks deste controller no template via ng-click etc. Encontrou resposta here .


Answer #3

Gostaria de adicionar para referência:

A execução de código do controlador duplo também pode ser causada referenciando o controlador em uma diretiva que também é executada na página.

por exemplo

return {

            restrict: 'A',
            controller: 'myController',
            link: function ($scope) { ....

Quando você também tem ng-controller = "myController" no seu HTML


Answer #4

No meu caso, encontrei duas visões usando o mesmo controlador.

$stateProvider.state('app', {
  url: '',
  views: {
    "[email protected]": {
      controller: 'CtrlOne as CtrlOne',
      templateUrl: 'main/one.tpl.html'
    },
    "[email protected]": {
      controller: 'CtrlOne as CtrlOne',
      templateUrl: 'main/two.tpl.html'
    }
  }
});

Answer #5

Eu descobri que o meu é chamado duas vezes porque eu estava chamando o método duas vezes do meu html.

`<form class="form-horizontal" name="x" ng-submit="findX() novalidate >
 <input type="text"....>
 <input type="text"....>
 <input type="text"....>
 <button type="submit" class="btn btn-sm btn-primary" ng-click="findX()"
</form>`

A seção destacada estava causando o findX () a ser chamado duas vezes. Espero que ajude alguém.


Answer #6

Para aqueles que usam a sintaxe ControllerAs, apenas declare o rótulo do controlador no $ routeprovider da seguinte forma:

$routeprovider
        .when('/link', {
            templateUrl: 'templateUrl',
            controller: 'UploadsController as ctrl'
        })

ou

$routeprovider
        .when('/link', {
            templateUrl: 'templateUrl',
            controller: 'UploadsController'
            controllerAs: 'ctrl'
        })

Depois de declarar o $ routeprovider, não forneça o controlador como na visualização. Em vez disso, use o rótulo na exibição.


Answer #7

Estive a coçar a cabeça sobre este problema com AngularJS 1.4 rc build, então percebi que nenhuma das respostas acima era aplicável desde que foi originada da nova biblioteca de roteadores para Angular 1.4 e Angular 2 no momento desta escrita. Portanto, estou colocando uma nota aqui para qualquer pessoa que possa estar usando a nova biblioteca de rotas Angular.

Basicamente, se uma página html contiver uma diretiva ng-viewport para carregar partes do seu aplicativo, clicando em um hiperlink especificado com ng-link faria com que o controlador de destino do componente associado fosse carregado duas vezes. A diferença sutil é que, se o navegador já tiver carregado o controlador de destino, ao clicar novamente no mesmo hiperlink, o controlador será invocado apenas uma vez.

Ainda não encontrei uma solução viável, embora eu acredite que esse comportamento seja consistente com a observação levantada por shaunxu , e esperamos que este problema seja resolvido na futura construção da nova biblioteca de rotas e junto com as versões do AngularJS 1.4.


Answer #8

O roteador de aplicativos especificou a navegação para MyController forma:

$routeProvider.when('/',
                   { templateUrl: 'pages/home.html',
                     controller: MyController });

Mas eu também tinha isso em home.html :

<div data-ng-controller="MyController">

Isso digeriu o controlador duas vezes. Remover o atributo data-ng-controller do HTML resolveu o problema. Alternativamente, a propriedade controller: poderia ter sido removida da diretiva de roteamento.

Esse problema também aparece ao usar navegação com guias. Por exemplo, app.js pode conter:

  .state('tab.reports', {
    url: '/reports',
    views: {
      'tab-reports': {
        templateUrl: 'templates/tab-reports.html',
        controller: 'ReportsCtrl'
      }
    }
  })

A guia HTML de relatórios correspondentes pode se assemelhar a:

<ion-view view-title="Reports">
  <ion-content ng-controller="ReportsCtrl">

Isso também resultará na execução do controlador duas vezes.



Answer #10

Eu tive essa inicialização dupla acontecer por um motivo diferente. Para algumas transições de rota em meu aplicativo, eu queria forçar a rolagem para perto do topo da página (por exemplo, em resultados de pesquisa paginados ... clique em próximo para ir ao topo da página 2).

Eu fiz isso adicionando um ouvinte ao $rootScope $on $viewContentLoaded que (com base em certas condições) executadas

$location.hash('top');

Inadvertidamente isso estava fazendo com que minhas rotas fossem reavaliadas e os controladores fossem reinicializados


Answer #11

Eu tenho o mesmo problema em [email protected] , e isso porque a barra extra no final da rota regex:

.when('/goods/publish/:classId/', option)

para

.when('/goods/publish/:classId', option)

e funciona corretamente.


Answer #12

Eu tive o mesmo problema e depois de tentar todas as respostas eu finalmente encontrei que eu tinha uma diretiva na minha opinião que estava ligada ao mesmo controlador.

APP.directive('MyDirective', function() {
  return {
    restrict: 'AE',
    scope: {},
    templateUrl: '../views/quiz.html',
    controller: 'ShowClassController'
}
});

Depois de remover a diretiva, o controlador deixou de ser chamado duas vezes. Agora minha pergunta é, como pode usar esta diretiva vinculada ao escopo do controlador sem esse problema?


Answer #13

Se você sabe que seu controlador está involuntariamente executando mais de uma vez, tente uma pesquisa em seus arquivos para obter o nome do controlador problemático, ex: search: MyController em todos os arquivos. É provável que tenha copiado e colado em algum outro arquivo html / js e você tenha esquecido de alterá-lo quando tiver desenvolvido ou usado esses parciais / controladores. Fonte: Eu cometi este erro


Answer #14

No meu caso, renomear o controlador para um nome diferente resolveu o problema.

Houve um conflito de nomes de controladores com o módulo " angular-ui-tree ": renomeei meu controlador de "CatalogerTreeController" para " TreeController " e então este controlador começa a ser iniciado duas vezes na página onde a diretiva " ui-tree " é usada porque esta diretiva usa o controlador chamado " TreeController ".


Answer #15

Eu tive o mesmo problema, em um aplicativo simples (sem roteamento e uma simples referência ng-controller) e o construtor do meu controlador rodou duas vezes. Finalmente, descobri que meu problema era a declaração a seguir para auto-bootstrap meu aplicativo AngularJS na minha visão Razor

<html ng-app="mTest1">

Eu também tenho bootstrapped manualmente usando angular.bootstrap ou seja

angular.bootstrap(document, [this.app.name]);

então removendo um deles, funcionou para mim.


Answer #16

AngularJS docs - ngController
Observe que você também pode anexar controladores ao DOM declarando-o em uma definição de rota por meio do serviço $ route. Um erro comum é declarar o controlador novamente usando o ng-controller no próprio modelo. Isso fará com que o controlador seja conectado e executado duas vezes.

Quando você usa ngRoute com a diretiva ng-view , o controlador é anexado a esse elemento dom por padrão (ou ui-view se você usa o ui-roteador). Então você não precisará anexá-lo novamente no modelo.


Answer #17

Só quero adicionar mais um caso quando o controlador pode iniciar duas vezes (isso é real para o angular.js 1.3.1):

<div ng-if="loading">Loading...</div>
<div ng-if="!loading">
    <div ng-view></div>
</div>

Neste caso, $ route.current já estará definido quando ng-view for init. Isso causa dupla inicialização.

Para corrigi-lo basta mudar ng-if para ng-show / ng-hide e tudo vai funcionar bem.





angularjs