2016-01-21 2 views
4

Я добавляю AngularJS 1.x в форму для редактирования заказов (возможность изменить дату, доставку и адрес в этом примере). У меня есть Рубин на Rails JSON API с несколькими конечными точками:AngularJS Как преобразовать запросы для Rails API

GET /addresses 
[{ id: 1, line1: "...", line2: "...", zip: "..." }, ...] 

GET /shippings 
[{ id: 1, name: "priority" }, ...] 

GET /orders/:id 
{ date: "...", 
    shipping: { id: 1, name: "priority" }, 
    address: { id: 1, line1: "...", line2: "...", zip: "..." } } 

PATCH /orders/:id 
{ date: "...", 
    shipping_id: 1, 
    address_attributes: { line1: "...", line2: "...", zip: "..." } } 

Внутри моей OrdersController я имею следующее:

var app = angular.module('app'); 

app.controller('OrdersController', ['$scope', 'Order', 'Address', 'Shipping', 
    function($scope, Order, Address, Shipping) { 
    $scope.order = Order.get({ id: 123 }); 
    $scope.addresses = Address.query(); 
    $scope.shippings = Shipping.query(); 

    $scope.save = function() { 
     $scope.order.$save(function() { 
     // ... 
     }, function(error) { alert(error); }); 
    }; 
    } 
]); 

Моя форма довольно проста:

<form ng-submit="save()"> 
    <input type="date" ng-model="order.date" /> 

    <select ng-model="order.shipping" 
    ng-options="option.name for option in shippings track by option.id"> 
    </select> 

    <input type="text" ng-model="order.address.line1" /> 
    <input type="text" ng-model="order.address.line2" /> 
    <input type="text" ng-model="order.address.zip" /> 

    <input type="submit" value="Save"/> 
</form> 

спасбросков функция попадает в мою конечную точку API, однако параметры неверны. Мне нужно найти способ преобразования между этими форматами:

{ date: "...", shipping: { ... }, address: { ... } } 
{ date: "...", shipping_id: 1, address_attributes: { ... } } 

Каков рекомендуемый способ сделать это в AngularJS? Это что-то, что нужно сделать через перехватчики? Должен ли я создавать новый ресурс Order и копировать атрибуты в желаемом порядке?

ответ

1

AngularJS $resource поддерживает настройки transformRequest и transformResponse на каждое действие (см. https://docs.angularjs.org/api/ngResource/service/$resource). Для примера:

angular.module("app").factory("OrderSerializer", function() { 
    return function(data) { 
    var parameters = angular.copy(data); 

    if (parameters.address) { 
     parameters.address_attributes = parameters.address; 
     delete parameters.address; 
    } 

    if (parameters.shipping && parameters.s.id) { 
     parameters.shipping_id = parameters.shipping.id; 
     delete parameters.shipping; 
    } 

    return parameters; 
    }; 
}); 

angular.module("app").factory("Order", ["$resource", "OrderSerializer", 
    function($resource, serializer) { 
    return $resource("...", { id: "@id" }, { 
     "save": { 
     method: "...", 
     transformRequest: [serializer, angular.toJson], 
     }, 
    }); 
    } 
]); 

Если продвинутые преобразования необходимы, может быть стоит посмотреть в качестве замены для ng-resource, таких как restangular.

+0

Возможный дубликат http://stackoverflow.com/a/35037641/630544 :-) –

1

У Angular's $http$resource) сервис имеет конфигурационный параметр transformRequest, который принимает функцию (или массив функций), которая может использоваться для преобразования данных запроса.

Предполагая, что вы используете одну из этих служб, это будет наиболее подходящее место для обработки сопоставления объектов.

Пример: JSFiddle

function MyController($http) { 
    var vm = this; 

    vm.data = { 
    message: 'Hello World!' 
    }; 

    vm.mapper = function(data, headersGetter) { 
    data.greeting = data.message; 
    delete data.message; 
    return data; 
    }; 

    $http({ 
    url: '/path/to/endpoint', 
    method: 'PUT', 
    data: vm.data, 
    transformRequest: [vm.mapper, angular.toJson] 
    }); 
} 

Обратите внимание, что, в моем примере, я использую массив функций для преобразования моего запроса. Это связано с тем, что по умолчанию $http использует angular.toJson для строения объекта данных, и я все еще хочу, чтобы это поведение выполнялось после выполнения моей функции mapper.

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