AngularJS 실행 컨트롤러를 두 번 결합


532

AngularJS는 $watch이벤트 와 같은 모델 코드를 두 번, 때로는 모델 상태를 지속적으로 확인하는 등 두 번 실행합니다 .

그러나 내 코드 :

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

//...

내 DB에 2 개의 레코드를 삽입하여 두 번 실행됩니다. 나는 이것에 대해 오랫동안 머리를 두드리면서 분명히 배우고 있습니다!


104
컨트롤러가 두 번 실행중인 경우 Angular 앱을 두 번 초기화하지 않았는지 확인하십시오 ( ng-app수동 부트 스트랩을 사용하여 수동 으로 초기화하여 ). 또한 컨트롤러를 여러 요소에 연결했는지 확인하십시오 (ng-controller 사용).
Stewie

7
"수동 부트 스트랩"의 의미를 설명 할 수 있습니까?
스포츠


2
로깅 문제를 해결할 때 콘솔 로그가 두 번 실행되는 것을 보았을 때 상속 한 앱에서 컨트롤러의 중복 동작을 발견했습니다. 첫 번째 로그 화재에는 값이 있었지만 두 번째 로그 화재는 정의되지 않았습니다. 컨트롤러에 대한 HTML ng-controller 지시문을 제거한 후 정의되지 않은 두 번째 콘솔 로그 발생이 사라졌습니다.
다니엘 Nalbach

2
angular.js가 두 번 추가되면 이런 일도 발생할 수 있습니다
Mohit

답변:


1050

앱 라우터는 다음 MyController과 같이 탐색을 지정했습니다 .

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

그러나 나는 또한 이것을 가지고 있었다 home.html:

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

이것은 컨트롤러를 두 번 소화했습니다. data-ng-controllerHTML 에서 속성을 제거하면 문제가 해결되었습니다. 또는 controller:라우팅 지시문에서 속성을 제거했을 수 있습니다.

이 문제는 탭 탐색을 사용할 때도 나타납니다. 예를 들어, 다음 app.js을 포함 할 수 있습니다.

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

해당 보고서 탭 HTML은 다음과 유사 할 수 있습니다.

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

또한 컨트롤러를 두 번 실행합니다.


4
이것은 코드를 빗질 한 후 몇 시간이 지난 후에 이것을 남기는 가장 좋은 장소 인 것 같습니다. 그러나로 변경 <div ng-view>...하면 <div class="ng-view">...이 문제가 저를 위해 중단되었습니다. 나는 이전 에이 행동을 보지 못했지만 다른 누군가도 이것을 가지고 있습니다.
Phix


1
경로에서 컨트롤러를 선언하고 html 페이지 자체에서 다른 컨트롤러를 선언하는 방법이 있습니까? 작동하고 충돌하지 않는 방법? 아니면 이것이 불필요합니까?
사상가

1
아마도 불필요합니다. 대신 몇 가지 지시문을 사용하십시오.
그렉

2
@Josh를 HTML에 그대로두면 유연성이 떨어집니다. 템플릿을 하나의 컨트롤러에 직접 연결하고 있습니다. 라우팅과 함께 ctrl을 구문으로 사용할 수 있습니다.
Greg

127

AngularJS 문서-ngController
$ route 서비스를 통해 경로 정의에서 컨트롤러를 선언하여 DOM에 컨트롤러를 연결할 수도 있습니다. 일반적인 실수는 템플릿 자체에서 ng-controller를 사용하여 컨트롤러를 다시 선언하는 것입니다. 이로 인해 컨트롤러가 두 번 연결되고 실행됩니다.

ng-view지시문 과 함께 ngRoute를 사용 하면 컨트롤러는 기본적으로 해당 dom 요소에 연결됩니다 (또는 ui-router를 사용하는 경우 ui-view). 따라서 템플릿에 다시 첨부 할 필요가 없습니다.


답변이 중복되었습니다. 저자는 이미 같은 말을했다. 페이지 끝까지 스크롤 다운하십시오.
Iago

4
저자가 그것을 옳은 방법으로 부수적으로 작성하는 것이 혼란 스러웠습니다. 문서의 인용문은 질문에 명확하게 대답합니다. 그리고 많은 사람들이 문서에 대한 링크가 도움이 될 것이라고 확신합니다.
shxfee

이것은 컨트롤러가 두 번 실행되는 문제를 해결했습니다. 내가 한 것은 템플릿에서 ng-controller를 제거하고 이제는 한 번만 실행하는 것입니다.
torbenrudgaard

70

방금이 작업을 수행했지만 문제는 허용되는 답변과 다릅니다. 나는 이것을 내 미래의 자아를 위해 여기에 남겨두고 그것을 고치기 위해 밟은 단계를 포함시킵니다.

  1. 중복 컨트롤러 선언 제거
  2. 경로에서 슬래시 확인
  3. 확인 ng-ifs
  4. 불필요한 래핑 ng-view호출을 확인하십시오 (실수 ng-view로 래핑되어 실제로 실제 래핑되었습니다 ng-view. 컨트롤러에 세 번의 호출이 발생했습니다.)
  5. Rails를 사용하는 경우 파일 에서 turbolinksgem을 제거 해야 application.js합니다. 나는 그것을 발견하기 위해 하루 종일 낭비했다. 여기에 답변이 있습니다 .
  6. ng-app 및 부트 스트랩으로 앱을 두 번 초기화합니다. AngularJS 실행 컨트롤러를 두 번 결합
  7. 자체 컨트롤러를 정의하고 ng-click 등을 통해 템플릿에서이 컨트롤러의 콜백을 사용하는 지시문의 '링크'기능에서 전체 요소에 $ compile을 사용하는 경우 여기 에서 답변을 찾았 습니다 .

5. Rails에있는 경우 파일 turbolinks에서 gem을 제거 해야 application.js합니다. 그것은 나를 미치게했다. 진짜 고통. 찾을 수 대답 여기
18augst

6. ng-app 및 부트 스트랩으로 앱을 두 번 초기화합니다. stackoverflow.com/questions/15535336/…
thadeuszlay

1
감사 . 나를 위해, 일한 것은 경로의 끝에 슬래시를 두는 것이었다
Pramod Sharma

백만 감사합니다, 이것에 대한 내 머리를 깨고 있었다. 결국 7 번이되었습니다! (항상 마지막 것 ...).
Rabbi Shuki Gur

와우, 믿거 나 말거나, 나는 당신의 명부에있는 모든 것을 겪었고, 여전히 문제가 있습니다.
Jacob Stamm

14

컨트롤러가 두 번 초기화 할 수있는 경우를 하나 더 추가하고 싶습니다 (angular.js 1.3.1에 해당).

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

이 경우 ng-view가 초기화 될 때 $ route.current가 이미 설정되어 있습니다. 이중 초기화가 발생합니다.

이 문제를 해결하려면 ng-if를 ng-show / ng-hide로 변경하면 모두 잘 작동합니다.


그것은, 그것은 probleme가 아니라 겨-경우 겨 쇼 / ng를 숨기기가 해제하지 않는 동안 나는 겨 쇼 / ng를 숨기기를 사용하는 대신 겨-경우, 나는이 NG-볼 수 있었다, 나에게 도움이
디미트리 Kopriwa

정말 감사합니다. 이 접근법은 내 문제를 해결했습니다. ui-view컨트롤러를 두 번 호출 한 동일한 전화를 두 번 호출 했습니다.
curlyreggie

7

참조를 위해 추가하고 싶습니다 :

페이지에서 실행되는 지시문에서 컨트롤러를 참조하여 이중 컨트롤러 코드 실행이 발생할 수도 있습니다.

예 :

return {

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

HTML에 ng-controller = "myController"가있는 경우


이것에 대한 해결책은 무엇입니까?
Sagar Bhosale

1
하나만 사용하십시오.
gb2d

7

Angular 1.3 이상에서 angular-ui-router 를 사용할 때 경로 전환시 뷰를 두 번 렌더링 하는 데 문제가있었습니다 . 그 결과 컨트롤러도 두 번 실행되었습니다. 제안 된 솔루션 중 어느 것도 나를 위해 일하지 않았습니다.

그러나 angular-ui-router0.2.11에서 0.2.13으로 업데이트 하면 문제가 해결되었습니다.


6

내 응용 프로그램 과이 문제에 대한 비트에 대한 모든 종속성을 찢어 버렸습니다 (자세한 내용 : AngularJS 앱이 두 번 시작됩니다 (일반적인 솔루션을 시도했습니다 ..) )

그리고 결국, 그것은 모두 Batarang Chrome 플러그인의 결함이었습니다.

에서 해결 이 답변 :

나는 누군가의 목록에서 가장 먼저 코드를 변경하기 전에 게시물마다 그것을 비활성화하는 것이 좋습니다.


이것은 내 문제였다. 플러그인은 Angular 앱의 이중 인스턴스를 실행하므로 범위 정보를 제공 할 수 있습니다 (초기 인스턴스를 사용할 수없는 이유는 알 수 없음).
rgdigital

나는 그것이 도움이되어 기쁘다. 이것을 알아내는 데 시간이 걸렸다.
Lewis

5

컨트롤러가 실수로 두 번 이상 실행되고 있음을 알고 있으면 파일을 통해 문제가있는 컨트롤러의 이름을 검색하십시오 (예 : search : MyController through My files). 아마도 다른 html / js 파일에 복사하여 붙여 넣을 수 있으며 부분 / 컨트롤러를 개발하거나 사용할 때 파일을 변경하는 것을 잊어 버렸습니다. 출처 : 나는이 실수를했다


5

간단한 응용 프로그램 (라우팅 및 간단한 ng 컨트롤러 참조가없는)에서 동일한 문제가 발생했으며 컨트롤러의 생성자가 두 번 실행되었습니다. 마지막으로, 내 문제는 내 Razor보기에서 AngularJS 응용 프로그램을 자동 부팅하는 다음 선언이라는 것을 알았습니다.

<html ng-app="mTest1">

또한 angular.bootstrap을 사용하여 수동으로 부트 스트랩했습니다.

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

그래서 그들 중 하나를 제거하면 나를 위해 일했습니다.


4

어떤 경우에는 다음과 같이 지시문을 정확하게 닫지 않으면 지시문이 두 번 실행됩니다.

<my-directive>Some content<my-directive>

이것은 지시문을 두 번 실행합니다. 또한 지시문이 두 번 실행되는 경우가 종종 있습니다.

index.html TWICE에 지시문을 포함시키지 마십시오 !


또한 UI- 라우터를 사용하는 경우 클래스 내에서 ui-view의 지시문 이름을 지정하면 이중 실행이 발생하는 것으로 보입니다. E 또는 <ui-view> </ ui-view>로 변경하면 이중 실행 문제가 해결됩니다.
SteveGSD

2

AngularJS 1.4 rc 빌드 로이 문제에 대해 내 머리를 긁었으므로 위의 답변은 이 글을 쓰는 시점에 Angular 1.4 및 Angular 2 용 새 라우터 라이브러리 에서 시작되었으므로 해당되는 답변이 없다는 것을 깨달았습니다 . 따라서 새로운 Angular 경로 라이브러리를 사용하는 사람을 위해 여기에 메모를 작성하고 있습니다.

기본적으로 html 페이지에 ng-viewport앱의 일부를로드하기위한 지시문이 포함 된 경우로 지정된 하이퍼 링크를 클릭하면 ng-link연관된 컴포넌트의 대상 컨트롤러가 두 번로드됩니다. 미묘한 차이점은 브라우저가 대상 컨트롤러를 이미로드 한 경우 동일한 하이퍼 링크를 다시 클릭하면 컨트롤러를 한 번만 호출한다는 것입니다.

아직 실행 가능한 해결 방법을 찾지 못했지만이 동작이 shaunxu가 제기 한 관찰과 일치한다고 생각하지만 향후이 새로운 경로 라이브러리 빌드와 AngularJS 1.4 릴리스 에서이 문제가 해결되기를 바랍니다.


2

필자의 경우 동일한 컨트롤러를 사용하여 두 개의 뷰를 찾았습니다.

$stateProvider.state('app', {
  url: '',
  views: {
    "viewOne@app": {
      controller: 'CtrlOne as CtrlOne',
      templateUrl: 'main/one.tpl.html'
    },
    "viewTwo@app": {
      controller: 'CtrlOne as CtrlOne',
      templateUrl: 'main/two.tpl.html'
    }
  }
});

2

내가 겪고있는 문제는 접할 수도 있지만 인터넷 검색 으로이 질문에 도달했기 때문에 이것이 적절할 수 있습니다. UI 라우터를 사용할 때 문제가 발생하면 브라우저 새로 고침 버튼으로 페이지를 새로 고칠 때만 문제가 발생합니다. 앱은 부모 추상 상태의 UI 라우터를 사용하고 자식은 부모 상태를 해제합니다. 앱 run()기능에는 $state.go('...child-state...')명령이 있습니다. 부모 상태는을 사용하며 resolve처음에는 자식 컨트롤러가 두 번 실행되고 있다고 생각했습니다.

URL에 해시가 추가되기 전에 모든 것이 정상입니다.
www.someoldwebaddress.org

그런 다음 UI 라우터가 URL을 수정하면
www.someoldwebaddress.org#/childstate

... 그리고 나는 때 브라우저 새로 고침 버튼으로 페이지를 새로 고침$stateChangeStart두 번 화재 및 각 시점 childstate.

resolve부모 상태에 두 번 발사되는 것입니다.

아마도 이것은 kludge 일 것이다. 그럼에도 불구하고 이것은 나를 위해 문제를 제거하는 것처럼 보입니다. $stateProvider처음 호출 된 코드 영역 에서 먼저 window.location.hash 가 빈 문자열 인지 확인하십시오 . 그렇다면 모든 것이 좋습니다. 그렇지 않은 경우 window.location.hash 를 빈 문자열 로 설정하십시오 . 그렇다면 $state두 번이 아니라 한 번만 어딘가에 가려고 하는 것 같습니다 .

또한 앱의 기본값 run과 에 의존하지 않으려면 state.go(...)해시 값을 캡처하고 해시 값을 사용하여 페이지 새로 고침 직전의 하위 상태를 확인하고 해당 영역에 조건을 추가하십시오. 을 설정하는 코드 state.go(...)입니다.


1

내 경우에는 내가 사용한 URL 패턴 때문이었습니다.

내 URL은 / ui / project / : parameter1 / : parameter2와 같습니다.

모든 상태 변화에서 paramerter2가 필요하지 않았습니다. 두 번째 매개 변수가 필요하지 않은 경우 내 URL은 / ui / project / : parameter1 /과 같습니다. 따라서 상태가 변경 될 때마다 컨트롤러를 두 번 새로 고칩니다.

해결책은 parameter2를 빈 문자열로 설정하고 상태를 변경하는 것입니다.


1

이 이중 초기화가 다른 이유로 발생했습니다. 내 응용 프로그램의 일부 경로 전환의 경우 페이지 상단 근처로 강제로 스크롤하고 싶었습니다 (예 : 페이지가 매겨진 검색 결과에서 ... 다음을 클릭하면 2 페이지 상단으로 이동합니다).

나는 $rootScope $on $viewContentLoaded(특정 조건에 따라) 실행 된 리스너를 추가하여 이를 수행했습니다.

$location.hash('top');

실수로 이로 인해 내 경로가 재평가되고 컨트롤러가 다시 초기화되었습니다.



1

필자의 경우 컨트롤러 이름을 다른 이름으로 바꾸면 문제가 해결되었습니다.

" angular-ui-tree "모듈 과 컨트롤러 이름충돌했습니다. 컨트롤러의 이름 을 "CatalogerTreeController"에서 " TreeController "로 바꾼 다음이 컨트롤러는 " ui-tree "지시문이 사용 된 페이지에서 두 번 시작되기 시작합니다. 이 지시어는 " TreeController " 라는 컨트롤러를 사용합니다 .


1

ControllerAs 구문을 사용하는 경우 $ routeprovider에서 컨트롤러 레이블을 다음과 같이 선언하십시오.

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

또는

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

$ routeprovider를 선언 한 후에는 그림과 같이 컨트롤러를 제공하지 마십시오. 대신보기에서 레이블을 사용하십시오.


0

나는 같은 문제가 있었고 모든 대답을 시도한 후에 마침내 같은 컨트롤러에 바인딩 된 내 견해에 지시어가 있음을 알았습니다.

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

지시문을 제거한 후 컨트롤러 호출이 두 번 중지되었습니다. 이제 내 질문은이 지시문을 컨트롤러 범위에 바인딩하지 않고 어떻게 사용할 수 있습니까?


0

방금 내 문제를 해결했는데 실제로 실망했습니다. 이온 하이브리드 앱인 ui-router v0.2.13을 사용했습니다. 제 경우에는 epub.js를 사용하는 epub 리더가 있는데, 책 라이브러리로 이동하여 다른 책을 선택하면 "문서를 찾을 수 없습니다"라고 지속적으로보고하고 있습니다. 다시로드하면 브라우저 북이 완벽하게 렌더링되었지만 다른 책을 선택하면 같은 문제가 다시 발생합니다.

내 해결은 매우 간단했습니다. 난 그냥 내 reload:true에서 제거$state.go("app.reader", { fileName: fn, reload: true });LibraryController


0

에서 같은 문제가 있으며 정규식 경로 끝에 여분의 슬래시angular-route@1.6.7있기 때문에 :

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

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

제대로 작동합니다.


0

여기에 내 사건을 추가하기 만하면됩니다.

angular-ui-router 를 사용하고있었습니다.$state.go('new_state', {foo: "foo@bar"})

encodeURIComponent 를 매개 변수에 추가 하면 문제가 사라졌습니다 $state.go('new_state', {foo: encodeURIComponent("foo@bar")}).

어떻게 된 거예요? 매개 변수 값의 문자 "@"은 URL에서 허용되지 않습니다. 결과적으로, angular-ui-router는 컨트롤러를 두 번 만들었습니다. 첫 번째 생성 중에는 원래 "foo @ bar"를 통과했으며 두 번째 생성 중에는 인코딩 된 버전 "foo % 40bar"를 전달했습니다. 위와 같이 매개 변수를 명시 적으로 인코딩하면 문제가 해결되었습니다.


-1

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

강조 표시된 섹션으로 findX ()가 두 번 호출되었습니다. 그것이 누군가를 돕기를 바랍니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.