AngularJS. 컨트롤러 구성 요소 외부에서 컨트롤러 기능을 호출하는 방법


190

웹 페이지의 어느 곳에서나 컨트롤러 구성 요소 외부에서 컨트롤러 아래에 정의 된 함수를 호출하려면 어떻게해야합니까?

"get"버튼을 누르면 완벽하게 작동합니다. 그러나 div 컨트롤러 외부에서 호출해야합니다. 논리는 : 기본적으로 내 사업부는 숨겨져 있습니다. 탐색 메뉴 어딘가에 버튼을 누르면 내 div를 표시하고 "get"기능을 실행해야합니다. 어떻게하면 되나요?

내 웹 페이지는 다음과 같습니다

<div ng-controller="MyController">
  <input type="text" ng-model="data.firstname" required>
  <input type='text' ng-model="data.lastname" required>

  <form ng-submit="update()"><input type="submit" value="update"></form>
  <form ng-submit="get()"><input type="submit" value="get"></form>
</div>

내 js :

   function MyController($scope) {
      // default data and structure
      $scope.data = {
        "firstname" : "Nicolas",
        "lastname" : "Cage"
      };

      $scope.get = function() {
        $.ajax({
           url: "/php/get_data.php?",
           type: "POST",
           timeout: 10000, // 10 seconds for getting result, otherwise error.
           error:function() { alert("Temporary error. Please try again...");},
           complete: function(){ $.unblockUI();},
           beforeSend: function(){ $.blockUI()},
           success: function(data){
            json_answer = eval('(' + data + ')');
            if (json_answer){
                $scope.$apply(function () {
                  $scope.data = json_answer;
            });
            }
        }
    });
  };

  $scope.update = function() {
    $.ajax({
        url: "/php/update_data.php?",
        type: "POST",
        data: $scope.data,
        timeout: 10000, // 10 seconds for getting result, otherwise error.
        error:function() { alert("Temporary error. Please try again...");},
        complete: function(){ $.unblockUI();},
        beforeSend: function(){ $.blockUI()},
        success: function(data){ }
      });
    };
   }

2
"... 내비게이션 메뉴 어딘가에 버튼을 누르십시오 ..."라고 말하면,이 네비게이션이 다른 컨트롤러의 일부이고 다른 컨트롤러 get()에서 MyController 를 호출 하겠습니까?
callmekatootie

1
현재 네비게이션 메뉴는 컨트롤러가 아닙니다. 그냥 html. html / javascript에서 컨트롤러 함수를 호출 할 수 있는지 확실하지 않기 때문에이 질문을 게시했습니다. 그러나 네, 탐색 메뉴를 별도의 컨트롤러로 만드는 것이 논리적입니다. NavigationMenu.Controller에서 MyController.get () 함수를 호출하는 방법은 무엇입니까?
Pavel Zdarov

답변:


331

컨트롤러 외부에서 컨트롤러 기능을 호출하는 방법은 다음과 같습니다.

angular.element(document.getElementById('yourControllerElementID')).scope().get();

get()컨트롤러의 기능은 어디에 있습니까 ?

당신은 전환 할 수 있습니다

document.getElementById('yourControllerElementID')` 

$('#yourControllerElementID')

jQuery를 사용하는 경우

또한 함수가 View에서 무언가를 변경하는 것을 의미하는 경우 전화해야합니다.

angular.element(document.getElementById('yourControllerElementID')).scope().$apply();

변경 사항을 적용합니다.

한 가지 더, 페이지가로드 된 후 범위가 초기화되므로 페이지가로드 된 후에는 범위 외부에서 메소드를 호출해야합니다. 그렇지 않으면 스코프에 전혀 도달하지 못할 것입니다.

최신 정보:

최신 버전의 각도에서는

angular.element(document.getElementById('yourControllerElementID')).injector().‌​get('$rootScope')

그리고 그렇습니다, 이것은 실제로 나쁜 습관 이지만 때로는 때로는 더럽고 더러운 일이 필요합니다.


30
Angular의 철학은 DOM 코드를 Angular 코드와 혼합하지 않기 때문에 코드 냄새처럼 보입니다 ...
JoeCool

8
따라서 DOM 코드를 Angular 코드와 혼합하지 않을 경우 Angular 컨트롤러의 변수 변경에 대한 응답으로 특정 JQuery 애니메이션을 시작하려면 어떻게해야합니까? 컨트롤러에서하는 것이 쉽지는 않지만, 어떻게해야할지 모르겠습니다
Jan

3
$apply코드를 함수에 래핑하기 전까지 는 부분적으로 작업 할 수 없었습니다...scope.$apply(function() { scope.get() });
surfitscrollit

2
실제로 angular.element(document.getElementById('yourControllerElementID')).scope().controller; For ex로 컨트롤러에 액세스 할 수 있습니다 . 사용하는 경우 : angular.element(document.getElementById('controller')).scope().get() 던지고 정의되지 않은 오류가 있지만 사용 angular.element(document.getElementById('controller')).scope().controller.get()하면 작동합니다.
vrunoa

2
이 솔루션이 Angular 1.4.9에서 더 이상 작동하지 않을 수 있습니까? 나는 액세스 할 수 없습니다 scope()에서 angular.element(...)이 정의되지 않은 및 각 요소 / 객체의 vardump이 기능이 있다고 돌려주는 때문에, scope에 위치해 있습니다 __proto__-object.
Smamatti

37

인터넷에서 예를 찾았습니다.

어떤 사람은이 코드를 작성하고 완벽하게 작동했습니다.

HTML

<div ng-cloak ng-app="ManagerApp">
    <div id="MainWrap" class="container" ng-controller="ManagerCtrl">
       <span class="label label-info label-ext">Exposing Controller Function outside the module via onClick function call</span>
       <button onClick='ajaxResultPost("Update:Name:With:JOHN","accept",true);'>click me</button>
       <br/> <span class="label label-warning label-ext" ng-bind="customParams.data"></span>
       <br/> <span class="label label-warning label-ext" ng-bind="customParams.type"></span>
       <br/> <span class="label label-warning label-ext" ng-bind="customParams.res"></span>
       <br/>
       <input type="text" ng-model="sampletext" size="60">
       <br/>
    </div>
</div>

자바 스크립트

var angularApp = angular.module('ManagerApp', []);
angularApp.controller('ManagerCtrl', ['$scope', function ($scope) {

$scope.customParams = {};

$scope.updateCustomRequest = function (data, type, res) {
    $scope.customParams.data = data;
    $scope.customParams.type = type;
    $scope.customParams.res = res;
    $scope.sampletext = "input text: " + data;
};



}]);

function ajaxResultPost(data, type, res) {
    var scope = angular.element(document.getElementById("MainWrap")).scope();
    scope.$apply(function () {
    scope.updateCustomRequest(data, type, res);
    });
}

데모

* 나는 약간의 수정을했다, 원본 참조 : font JSfiddle


2
감사합니다 Roger, 매우 유용합니다!
Eduardo

반드시 사용해야하는 레거시 jQuery 유효성 검사 라이브러리 작업 따라서, 이것은 1 : 라이브러리를 다시 작성하고 2 : 라이브러리를 랩핑하기위한 지시문을 작성합니다. 3 : 유효한 경우 각도 제출을 호출하는 코드 2 줄 ...
Michael K

적용을 사용하지 않으면보기 데이터를 업데이트하는 기능이 반영되지 않습니까?
Monojit Sarkar

13

솔루션 angular.element(document.getElementById('ID')).scope().get()은 각도 1.5.2에서 나를 위해 작동을 멈췄습니다. Sombody는 1.4.9에서도 작동하지 않는다는 의견을 언급했습니다. 범위를 전역 변수에 저장하여 수정했습니다.

var scopeHolder;
angular.module('fooApp').controller('appCtrl', function ($scope) {
    $scope = function bar(){
        console.log("foo");        
    };
    scopeHolder = $scope;
})

사용자 정의 코드에서 전화 :

scopeHolder.bar()

범위를이 방법으로 만 제한하려는 경우 전체 범위의 노출을 최소화합니다. 다음 기술을 사용하십시오.

var scopeHolder;
angular.module('fooApp').controller('appCtrl', function ($scope) {
    $scope.bar = function(){
        console.log("foo");        
    };
    scopeHolder = $scope.bar;
})

사용자 정의 코드에서 전화 :

scopeHolder()

이것은 구성 요소 내부에서도 나에게 효과적이었습니다. 시나리오에서 피할 수없는 "각도 외부에서 각도 물건을 호출하는 나쁜 습관"이외의 다른 방법으로 단점이 있습니까? stackoverflow.com/questions/42123120/…
RichC

도움을 주셔서 감사합니다. 한동안 해결책을 찾고있었습니다.
Ibrahim Amer

11

Dmitry의 대답은 잘 작동합니다. 방금 동일한 기술을 사용하여 간단한 예를 만들었습니다.

jsfiddle : http://jsfiddle.net/o895a8n8/5/

<button onclick="call()">Call Controller's method from outside</button>
<div  id="container" ng-app="" ng-controller="testController">
</div>

.

function call() {
    var scope = angular.element(document.getElementById('container')).scope();
      scope.$apply(function(){
        scope.msg = scope.msg + ' I am the newly addded message from the outside of the controller.';
    })
    alert(scope.returnHello());
}

function testController($scope) {
    $scope.msg = "Hello from a controller method.";
    $scope.returnHello = function() {
        return $scope.msg ; 
    }
}

7

차라리 공장에 컨트롤러에 대한 종속성으로 포함시키고 자합니다. http://jsfiddle.net/XqDxG/550/

myModule.factory('mySharedService', function($rootScope) {
    return sharedService = {thing:"value"};
});

function ControllerZero($scope, mySharedService) {
    $scope.thing = mySharedService.thing;

ControllerZero. $ inject = [ '$ scope', 'mySharedService'];


흠. @Anton은 아래 (5 월 13 일)에 모두 바이올린을 언급했습니다.
Jesse Chisholm

5

관련 범위가없는 메뉴를 사용하는 것이 올바른 방법인지 고려해 볼 가치가 있습니다. 실제로 각도가 아닙니다.

그러나 필요한 방법 인 경우 $ rootScope에 함수를 추가 한 다음 $ broadcast를 사용하여 이벤트를 보내 해당 함수 내에서이를 수행 할 수 있습니다. 그런 다음 컨트롤러는 $ on을 사용하여 해당 이벤트를 수신합니다.

범위없이 메뉴를 사용하게되면 고려해야 할 또 다른 사항은 여러 경로가있는 경우 모든 컨트롤러에 고유 한 upate가 있고 기능을 가져와야한다는 것입니다. (여러 컨트롤러가 있다고 가정합니다)


ControllerTwo에서 ControllerOne의 .get () 함수를 호출하는 방법에 대한 간단한 예를 들어 줄 수 있습니까? 내 논리는 각 컨트롤러가 자체 .get () .update () 함수를 갖도록하는 것입니다. 필요한 컨트롤러의 .get () 메뉴 항목에 따라 MainMenuController를 실행해야합니다.
Pavel Zdarov

ps, 내 코드는 아니지만 여러 컨트롤러가 기능을 공유하는 방법을 보여줍니다.
Anton

4

리소스에서 정보를 얻으려는 경우 $ http로 작업하는 데 다음을 수행합니다.

angular.module('services.value', [])

.service('Value', function($http, $q) {

var URL = "http://localhost:8080/myWeb/rest/";

var valid = false;

return {
    isValid: valid,
    getIsValid: function(callback){
        return $http.get(URL + email+'/'+password, {cache: false})
                    .success(function(data){
            if(data === 'true'){ valid = true; }
        }).then(callback);
    }}
    });

그리고 컨트롤러의 코드 :

angular.module('controllers.value', ['services.value'])

.controller('ValueController', function($scope, Value) {
    $scope.obtainValue = function(){
        Value.getIsValid(function(){$scope.printValue();});
    }

    $scope.printValue = function(){
        console.log("Do it, and value is " Value.isValid);
    }
}

컨트롤러에서 어떤 기능을 호출해야하는지 서비스에 보냅니다.


3

여러 개의 경로와 여러 개의 컨트롤러가 있으므로 허용되는 답변을 얻을 수 없습니다. 창에 기능을 추가하면 작동한다는 것을 알았습니다.

fooModule.controller("fooViewModel", function ($scope, fooService, $http, $q, $routeParams, $window, $location, viewModelHelper, $interval) {
    $scope.initFoo = function () {
        // do angular stuff
    }
    var initialize = function () {
        $scope.initFoo();
    }

    initialize();

    window.fooreinit = initialize;

}

그런 다음 컨트롤러 외부 에서이 작업을 수행 할 수 있습니다.

function ElsewhereOnThePage() {
    if (typeof(fooreinit) == 'function') { fooreinit(); }
}

0

컨트롤러 외부에서 각도 범위 기능을 호출하십시오.

// Simply Use "Body" tag, Don't try/confuse using id/class.

var scope = angular.element('body').scope();             
scope.$apply(function () {scope.YourAngularJSFunction()});      

-1

나는 Ionic 프레임 워크 사용자이며 현재 컨트롤러의 $ 범위를 지속적으로 제공하는 것으로 밝혀진 사람은 다음과 같습니다.

angular.element(document.querySelector('ion-view[nav-view="active"]')).scope()

주어진 컨트롤러 인스턴스 중에 만 사용 가능한 특정 DOM 요소를 대상으로하는 쿼리를 찾아 프레임 워크에 관계없이 대부분의 시나리오에 맞게 수정할 수 있다고 생각합니다.

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