2014-09-22 2 views
3

Построение простой панели управления в AngularJS + Rest API.Функция AngularJS доступна для нескольких контроллеров

Построен простой завод, который делает запрос API (GET, POST) и возвращает необходимые данные для успешного обратного вызова. Данные возврата должны быть обработаны и изменены $scope, так как API может возвращать ошибки поля на стороне сервера.

Я не могу построить обработку/изменение $scope на заводе, так как завод не имеет (и не должен) иметь доступ к области. Я бы предпочел не обрабатывать/применять в обратном вызове успеха, поскольку он будет повторяющимся (один раз для запроса API).

Что является лучшим «Угловым способом» для решения этой проблемы?

Одним из возможных решений является наличие функции вне приложения с угловым выражением, а затем просто передать ему объем и необходимые данные.

Это ощущение плохой работы (см. Ниже).

myApp.controller("saveForm", ["$scope", "api", function($scope, api), function() { 
    ... 
    $scope.submit = function() { 
     api("POST", url, $scope.data, function(data) { 
      //onSuccess 
      processData($scope, data); 
     }); 
    } 
    ... 
}]); 

myApp.factory('api', ['$http', function($http) { 
    return function(method, url, input, success, error) { 
     //Retrieve data from API. Note that factory DOES NOT have access to $scope. 
     $http(... 
    } 
}]); 

var processData = function(scope, data) { 
    angular.forEach(data, function(value, key)) { 
     scope.... 
    } 
} 

ответ

1

Не уверен, что я получил, но вы можете расширить контроллеры в подмешать образом:

Базовый контроллер

(function() { 
    'use strict'; 

    angular.module('Base', []); 

    function BaseController($scope, <injectables>, that) { 
    that.mixin1 = function() { 
    }; 

    that.mixin2 = function(arg1, arg2) { 
    }; 
    } 

    angular.module('Base').controller('BaseController', 
    ['$scope', '...', BaseController]); 
})(); 

Наследуется контроллер

(function() { 
    'use strict'; 

    angular.module('Derived', ['Base']); 

    function DerivedController($scope, $controller, ...) { 
    $controller('BaseController', { 
     '$scope' : $scope, 
     ... 
     'that' : this 
    }); 

    // this.mixin1 
    // this.mixin2 
    } 

    angular.module('Derived').controller('DerivedController', 
    ['$scope', '$controller', '...', DerivedController]); 
})(); 

N чтобы использовать функцию Angular's $controller для смешивания функциональности.

0

Почему бы не просто включить функцию в контроллер, которая ее обрабатывает? Это, как я обычно справиться с этим:

myApp.controller("saveForm", ["$scope", "api", function($scope, api), function() { 
    ... 
    $scope.submit = function() { 
     api("POST", url, $scope.data, function(data) { 
      //onSuccess 
      processData(data); 
     }); 
    } 
    function provessData(data){ 
     // do stuff to data 
     $scope.foo = data; 
    } 
    ... 
}]); 
+0

Это действительно работает, однако у меня есть несколько контроллеров, которым нужно будет использовать processData(). С этой реализацией я должен был бы включить функцию в каждый контроллер; дублирующий код. – Jason

+0

Попробуйте это: http://stackoverflow.com/questions/19614545/how-can-i-add-some-small-utility-functions-to-my-angularjs-application – Kolby

+0

Хорошо, поэтому в этом случае вы бы порекомендовали решение, которое я дал, но чувствовал себя грязным, поскольку он существовал за пределами приложения «Угловое». – Jason

0

Похоже, ваш контроллер делает слишком много работы и слишком много знает о действительном запросе (URL, метод «POST», и т.д.).

О преобразовании данных на заводе в контроллер, который ожидает контроллер. Фабрике не нужно ничего знать о сфере применения. Он просто преобразует данные в формат, который контроллер может использовать, а затем отправляет обратно. Таким образом, завод может повторно использоваться через контроллеры.

myApp.controller("saveForm", ["$scope", "api", function($scope, api), function() { 
    ... 
    $scope.submit = function() { 

// Call API.update and handle the deferred that is returned, which will be the transformed data 
     api.update($scope.data).then(function (transformedData) { 
      scope.... 

     }); 
    } 
    ... 
}]); 

myApp.factory('api', ['$http', '$q', function($http, $q) { 
    return { 
     update : function() { 

      var deferred = $q.defer(); 

      $http({ 
       method: "GET", 
       url: "your/url/path" 

      }).success(function(data) { 

       var transformedData; 

       // Perform data transformation here instead of in controllers 
       angular.forEach(data, function (value, key) { 
        transformedData..... 
       }); 

       deferred.resolve(transformedData); 
      }); 

      return deferred.promise; 
     } 
    } 
}]); 
+0

Это действительно работает, однако это не решает проблему. У меня есть несколько контроллеров, которые используют фабрику 'api' и обрабатывают данные одинаково и изменяют $ scope. Размещение его в каждом успешном обратном вызове приведет к большому дублированию кода. – Jason

0

Вы можете создать фабрику, которая возвращает вашу processData функции:

myApp.factory('processData', [function() { 
    return function(scope, data) { 
     angular.forEach(data, function(value, key)) { 
      scope.... 
     } 
    }; 
}]); 

А затем он впрыскивается угловым:

myApp.controller("saveForm", ["$scope", "api", "processData", function($scope, api, processData) { 
    ... 
    $scope.submit = function() { 
     api("POST", url, $scope.data, function(data) { 
      //onSuccess 
      processData($scope, data); 
     }); 
    } 
    ... 
}]); 

Преимущества этого подхода над иметь функцию, объявленный вне ДИ заключается в том, что по-прежнему легко высмеивать зависимость processData в ваших модульных тестах, если вам нужно.

Смежные вопросы