Reputation: 1553
I want to POST
data from a html form to the default action url but one hidden input depends on the data returned from a service call. When I use ng-submit
the $scope
doesn't get updated after the service call before the POST
is done. I can't use an Ajax POST
because I get an HTML page after the POST
.
The form looks like this:
<form name="payment" role="form" class="form-inline" ng-show="!loading" method="POST" action="{{paymentUrl}}" ng-submit="createOrder()" novalidate>
<input type="hidden" id="responseUrl" name="responseUrl" value="{{postPaymentUrl}}"/>
<input type="hidden" id="orderNumber" name="orderNumber" value="{{orderNumber}}"/>
<select class="form-control" id="paymentMethodBrand" name="paymentMethodBrand">
<option ng-repeat="paymentMethod in paymentMethods | orderBy:'method'" value="{{paymentMethod.method}}">{{paymentMethod.method}}</option>
</select>
<button type="submit" class="btn btn-default" translate="BUY"></button>
</form>
The url in the action
field gets filled correctly.
The createOrder
function in the controller is this:
$scope.createOrder = function () {
Payment.start($scope.selectedProduct)
.then(function (response) {
$scope.orderNumber = response.data.orderNumber;
});
};
The problem is that the hidden input orderNumber doesn't get filled before opening the actual action URL. Therefore the data that gets posted is incorrect.
Any thoughts on how to approach this? I'm using angularjs 1.2.16.
Upvotes: 1
Views: 1365
Reputation: 1315
The issue is that Payment.start
is setting $scope.orderNumber
asynchronously on the resolution of a promise, but the form submit happens immediately. Normally you'd prevent the default action in an Angular based form by omitting the action
attribute on the form, given that Angular is designed for a client-based application. But in your case you want the normal http post to take place, and that's unusual. That takes us on a trip outside "best-practices" land.
So, acknowledging that this is an unusual usage case, I'm going to offer a solution that's a little hackish. You could omit the action attribute from the form, then add it when the promise is resolved from Payment.start
, and only then trigger the form submit:
$scope.createOrder = function () {
Payment.start($scope.selectedProduct)
.then(function (response) {
$scope.orderNumber = response.data.orderNumber;
var form = $('#form-id');
form.attr('action', $scope.paymentUrl);
form.submit();
});
};
This is untested, but I think it should work for you.
Upvotes: 3