2013-12-16 25 views
13

Tôi rất xanh ở Angular, tôi thậm chí không chắc chắn tôi đã cấu trúc tìm kiếm cho điều này một cách chính xác. Toàn bộ chỉ thị và thuật ngữ dịch vụ vẫn còn làm tôi bối rối, nhưng đó không phải là câu hỏi của tôi.AngularJS - Gọi chức năng điều khiển từ một dịch vụ

Tôi đã đọc loạt bài xuất sắc lĩnh vực này để sao lưu: http://www.ng-newsletter.com/posts/beginner2expert-how_to_start.html

Đó là lý do tại sao tôi đang ở thời điểm này trong ứng dụng của tôi. Và tại sao tôi biết câu hỏi của tôi liên quan nhiều hơn đến mối quan hệ giữa các dịch vụ và bộ điều khiển. Thay vì liên quan đến cú pháp.

Vì vậy, đây là tổng quan về ứng dụng:

Tôi có một bộ điều khiển. Điều này xảy ra và nhận được một loạt dữ liệu trang trại cho người dùng bằng cách sử dụng một cuộc gọi AJAX tới một tệp PHP và hiển thị nó trên màn hình bằng cách sử dụng phạm vi $ của chính nó.

var masterApp = angular.module('masterApp', ['myFilters','commonControls']); 

masterApp.controller('MasterCtrl', ['$scope','$http', '$filter', 'commonFarmSelector', 
    function($scope, $http, $filter, commonFarmSelector){ 

     ... 

     $scope.masterCtrl.loadFarmData = function(farmId) { 
      var postdata = { 
       "farmId":farmId 
      }; 

      $http.post('/service/farmproduction', postdata).success(function (data) { 
       // Do stuff with the $scope using data 
      } 
     } 

     $scope.masterCtrl.loadFarms(); 
} 

Bạn sẽ thấy tôi đang tiêm một thứ gọi là "commonControls". Đây là một mô-đun tôi tạo ra để giữ các điều khiển sẽ được tái sử dụng bởi nhiều bộ điều khiển. Trong trường hợp này, một trường thả xuống có chứa danh sách các trang trại mà người dùng có quyền truy cập (cũng được gọi bằng AJAX):

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

commonControlsApp.controller('farmSelectorCtrl', ['$scope', '$http',function($scope, $http) { 

    $scope.farmSelectorCtrl ={} 

    // Change entire farm view when a different farm is selected 
    $scope.farmSelectorCtrl.switchUserFarm = function() { 
     var farmId = $scope.farmSelectorCtrl.selectedUserFarm; 
     $scope.masterCtrl.loadFarms(farmId); // !!! Direct link to masterCtrl 
    }; 

    // Get a list of the user's farms 
    $http.post('/service/userfarms').success(function (data) { 
     $scope.farmSelectorCtrl.userFarms = data.getFarmsPerUserResult.farmIds; 
    }); 

}]); 

Điều này làm việc tốt. Nhưng như bạn có thể thấy, farmSelector được liên kết trực tiếp với masterCtrl. Và hành vi của hàm loadFarmData đó là cụ thể cho bộ điều khiển đó. Nói cách khác, nó sẽ chỉ làm những điều áp dụng cho trang đó.

Vấn đề là trang trại nàyCông cụ sẽ được sử dụng trên các trang khác. Và hành vi chính xác của sự kiện thay đổi sẽ khác nhau đối với mỗi trang. Vì vậy, tôi đang đấu tranh để làm việc ra nơi mà hành vi này nên ngồi. Và làm thế nào nó sẽ được gọi là phụ thuộc vào bộ điều khiển bằng cách sử dụng farmSelector.

Bài viết tôi đã liên kết ở trên đề xuất trang trại nàyDanh sách phải nằm trong dịch vụ để có thể sử dụng lại ở nơi khác. Nhưng tôi vẫn còn bối rối về cách bạn có thể cung cấp cho một dịch vụ chung một hành động cụ thể để thực hiện khi một sự kiện được kích hoạt.

Trả lời

11

Tôi cũng khuyên bạn nên sử dụng một dịch vụ, vì lý do tương tự mà bài viết đề xuất. Nó cũng có một câu trả lời tuyệt vời cho vấn đề của bạn.

Thuật ngữ kỹ thuật cho những gì bạn muốn là hàm calback. Chính xác là một hành động cụ thể cần thực hiện khi một sự kiện được kích hoạt và phần Dịch vụ của bài viết cung cấp một ví dụ tốt về cách thực hiện điều này.

Hãy nhìn vào phần này của bài viết Dịch vụ (mà tôi đã cắt xuống đến những phần quan trọng)

angular.module('myApp.services', []) 
    .factory('githubService', ['$http', function($http) { 

    var doRequest = function(username) { 
     return $http({ 
     url: 'https://MySuperURL.com/getTheData' 
     }); 
    } 

    return { 
     events: doRequest 
    }; 

}]); 

Vì vậy, chúng tôi đã có một dịch vụ hiện nay, được gọi là githubService, trong đó có một phương pháp: events (mà thực sự chỉ là một tên khác cho doRequest;. tôi tiếp tục đổi tên để nó sẽ phù hợp với mã của bài viết)

Thành viên ẩn danh ở đây đằng sau hậu trường là $q API, mà đôi khi được gọi là API 'hứa hẹn'. Hàm $http trả về một đối tượng 'lời hứa', đó thực sự chỉ là một cách để mã theo dõi những gì sẽ xảy ra khi 'lời hứa' được thực hiện.Ví dụ: hãy xem mã tiếp theo này (một lần nữa, được sửa đổi từ phiên bản của bài viết):

app.controller('ServiceController', ['$scope', 'githubService', 
function($scope, githubService) { 

    // uses the $http service to call the GitHub API 
    // and returns the resulting promise 
    githubService.events(newUsername) 
    .success(function(data, status, headers) { 
     // do magic stuff with the result 
     // (which is in the data param) 
     $scope.events = data.data; 
    }) 
}); 

}]);

Đây là nơi 'ma thuật' đang diễn ra. Hãy nhìn vào cuộc gọi tới success() và bạn sẽ thấy rằng họ đang thực sự chuyển một số function sẽ được chạy khi yêu cầu hoạt động. Chức năng vẫn có quyền truy cập vào tất cả các biến trong ServiceController do đóng, vì vậy nó được phép sử dụng $scope và các biến khác. Tuy nhiên, có thể viết một phương thức success() khác nhau trong mỗi bộ điều khiển bằng cách chuyển một hàm khác nhau mỗi lần, cho phép nhiều bộ điều khiển thực hiện các hành động khác nhau. Khi yêu cầu kết thúc, nó sẽ gọi mọi hàm success mà nó đã được cung cấp.

Bạn có thể làm theo ví dụ mã này và nhận mô hình làm việc, nhưng tôi cũng khuyên bạn nên xem $q in angular và cũng xem bài viết này về callback functions. Bạn cần phải hiểu cả hai để thực sự có được những gì đang xảy ra, nhưng tin tốt là cả hai đều được sử dụng khá thường xuyên trong góc cạnh, vì vậy nó sẽ có giá trị thời gian của bạn.

+0

Tôi ước tôi đã thấy câu trả lời này trước một vài giờ đầu gãi làm thế nào để làm điều đó. Cảm ơn rất nhiều vì nỗ lực –

Các vấn đề liên quan