简体   繁体   English

从外部调用角度控制器的方法

[英]Call angular controller's method from outside

Here's the code: http://jsbin.com/rucatemujape/1/edit?html,js,console,output 这是代码: http : //jsbin.com/rucatemujape/1/edit?html,js,console,output

My question is how do I manually call method changeUser from JavaScript so the output HTML changes? 我的问题是如何从JavaScript手动调用方法changeUser以便输出HTML更改?

I can do this by executing (relies on jQuery) 我可以通过执行(依靠jQuery)来做到这一点

angular.element('body').scope().changeUser({fullName: 'John Doe'});
angular.element('body').scope().$apply()

But I want to know is there any better way? 但是我想知道还有什么更好的方法吗?

For example, in knockout.js I can execute viewModel.someFunction() any time and knockout correctly handles this. 例如,在基因敲除viewModel.someFunction() ,我可以随时执行viewModel.someFunction() ,基因剔除可正确处理此问题。

Why do I want to do this: because I want be able to change model from browser's console when debugging a code. 为什么要执行此操作:因为我希望能够在调试代码时从浏览器的控制台更改模型。

Edit: Another reason why I need this it's getting information from Restful Services and updating a model. 编辑:我需要它的另一个原因是它从Restful Services获取信息并更新模型。 Yes I can trigger that event by clicking a button with "ng-click" attribute but how to deal with events which are not initiated by user? 是的,我可以通过单击具有“ ng-click”属性的按钮来触发该事件,但是如何处理不是由用户启动的事件? For example, repeating ations from setInterval or something 例如,从setInterval或其他内容重复执行

 var myApp = angular.module('myApp', []); myApp.controller('MyController', function($scope, $timeout) { $scope.user = {}; $scope.count = 0; $scope.changeUser = function(user) { $scope.user = "MyName"; $scope.count++; // call function after 1 sec. $timeout($scope.changeUser, 1000); }; // initiate function $scope.changeUser(); }); 
 <!DOCTYPE html> <html ng-app="myApp"> <head> <meta charset="utf-8"> <title>JS Bin</title> <script src="//ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.0/angular.min.js"></script> </head> <body ng-controller="MyController" <span>Hello, {{user}}</span> <span>count, {{count}}</span> </body> </html> 

Use ng-click="changeUser()" to call the fucntion 使用ng-click =“ changeUser()”调用功能

http://jsbin.com/rucatemujape/2/edit http://jsbin.com/rucatemujape/2/edit

Controllers do not really expose "APIs" outside their own 'scope' (and below). 控制器实际上不会在自己的“作用域”(及下方)之外公开​​“ API”。 So either you do the Ajax call within the controller or you expose the "user data" to display. 因此,您可以在控制器内进行Ajax调用,也可以公开显示“用户数据”。

For example: Kostia Mololkin's answer's (in main comments) uses a global variable to share the data. 例如:Kostia Mololkin的答案(在主注释中)使用全局变量来共享数据。

Angular Way 角度方式

Here I present a more "angular way": the user is being handled by a "Service". 在这里,我提出了一种更加“有角度的方式”:用户正在由“服务”来处理。 Not clear which direction you wanted exactly. 不清楚你到底想哪个方向。 Anyway, this cannot hurt. 无论如何,这不会伤害。

Angular works best when you use "data" to "communicate state" instead of "events". 当您使用“数据”来“传达状态”而不是“事件”时,Angular效果最佳。 So the idea again is to arrange things so your data instance (ie "user") is the same between "{{user.fullname}}" and where the Ajax call is taking place. 因此,再次提出的想法是安排事情,以使“ {{user.fullname}}”与进行Ajax调用的位置之间的数据实例(即“用户”)相同。 There are many ways to skin a cat and it highly depends on the needs of your application. 有很多方法可以给猫皮剥皮,这在很大程度上取决于您的应用程序需求。 For example, if you build a singleton service for the ajax call, you can also have the data own by it AND exposed to the controller in some form or another (again, many ways of doing this). 例如,如果您为ajax调用构建单例服务,那么您也可以拥有它自己的数据,并以某种形式或另一种形式(同样有多种方式)将其公开给控制器。

NOTE: If you use angular's system to perform ajax calls (ie $http or $resource for instance) then you should never need to manually call "$apply()". 注意:如果您使用angular的系统执行ajax调用(例如$ http或$ resource),则永远不需要手动调用“ $ apply()”。 Btw, you should "wrap" calls with $apply() instead of calling it "afterwards" reason being to properly handle "throws". 顺便说一句,您应该使用$ apply()来“包装”调用,而不是“事后”调用它,以便正确处理“引发”。

Plunker example with Ajax/Rest call: 带有Ajax / Rest调用的Plunker示例:

http://plnkr.co/edit/SCF2XZCK5KQWkb4hZfOO?p=preview http://plnkr.co/edit/SCF2XZCK5KQWkb4hZfOO?p=preview

var myApp = angular.module('myApp', []);

myApp.factory('UserService', ['$http',function($http){

    // Extra parent object to keep as a shared object to 'simplify'
    // updating a child object
    var userData = {};

    userData.user = { fullName:'none' };

    function loadUserData(userid) {
      $http.get('restapi_getuserdata_'+userid+'.json').
        success(function(data, status, headers, config) {
          // update model
          userData.user = data;
        }).
        error(function(data, status, headers, config) {
          console.log("error: ", status);
        });
    }

    return {
      userData: userData,
      loadUserData: loadUserData
    };

}]);

myApp.controller('MyController', ['$scope', 'UserService', '$timeout', 
  function($scope, UserService, $timeout) {

    // shared object from the Service stored in the scope
    // there are many other ways, like using an accessor method that is 
    // "called" within the HTML  
    $scope.userData = UserService.userData;

}]);


myApp.controller('SomeOtherController', ['UserService', '$timeout', 
  function(UserService, $timeout) {

    // $timeout is only to simulate a transition within an app 
    // without relying on a "button".
    $timeout(function(){

      UserService.loadUserData(55);

    }, 1500);

}]);

HTML: HTML:

<html ng-app="myApp">
...
<body ng-controller="MyController">

  <span>Hello, {{userData.user.fullName}}</span>

  <!-- simulating another active piece of code within the App -->
  <div ng-controller="SomeOtherController"></div>

...

A variant using a getter method instead of data: 使用getter方法而不是数据的变体:

http://plnkr.co/edit/0Y8gJolCAFYNBTGkbE5e?p=preview http://plnkr.co/edit/0Y8gJolCAFYNBTGkbE5e?p=preview

var myApp = angular.module('myApp', []);

myApp.factory('UserService', ['$http',function($http){

    var user;

    function loadUserData(userid) {
      $http.get('restapi_getuserdata_'+userid+'.json').
        success(function(data, status, headers, config) {
          console.log("loaded: ", data);
          // update model
          user = data;
        }).
        error(function(data, status, headers, config) {
          console.log("error: ", status);
          user = undefined;
        });
    }

    return {
      getCurrentUser: function() { 
        return user || { fullName:"<none>" };
      },
      userLoggedIn: function() { return !!user; },
      loadUserData: loadUserData
    };

}]);

myApp.controller('MyController', ['$scope', 'UserService', '$timeout', 
  function($scope, UserService, $timeout) {

    // getter method shared
    $scope.getCurrentUser = UserService.getCurrentUser;
}]);


myApp.controller('SomeOtherController', ['UserService', '$timeout', 
  function(UserService, $timeout) {

    // $timeout is only to simulate a transition within an app 
    // without relying on a "button".
    $timeout(function(){

      UserService.loadUserData(55);

    }, 1500);

}]);

HTML: HTML:

<html ng-app="myApp">
...
<body ng-controller="MyController">

  <span>Hello, {{ getCurrentUser().fullName }}</span>

  <!-- simulating another active piece of code within the App -->
  <div ng-controller="SomeOtherController"></div>

...

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM