如何使用AngularJS指令从表单发送包含所有参数的POST请求?

问题描述 投票:0回答:1

我制作了一个AngularJS表单,通过指令集成了Stripe。在这里小提琴:https://jsfiddle.net/u5h1uece/

HTML:

<body ng-app="angularjs-starter">
  <script src="https://js.stripe.com/v3/"></script>
  <div ng-controller="MainCtrl">
    <form name="regForm" id="register-form">
      <label>Mail</label>
      <input ng-model="reg.email" type="email" name="username">
      <div stripe-validator 
           stripe-complete="stripeCompleted" 
           stripe-form-id="register-form"></div>
      <br>
      <button ng-model="reg.btn" ng-disabled="stripeCompleted === false || !regForm.username.$valid">Register</button>
    </form>
  </div>
</body>

JS:

var app = angular.module('angularjs-starter', []);

app.controller('MainCtrl', function($scope, $rootScope) {
  //Init stripe state via controller
  $scope.stripeCompleted = false;
});


app.directive('stripeValidator', function() {
  return {
    restrict: 'A',
    template: `
      <div id="stripe-wrapper">
        <div id="card-element"></div>
      </div>
      <small id="card-errors" class="text-danger" role="alert">{{ ccErrMsg }}</small>
      <input type="hidden" name="stripeToken" ng-value="stripeToken" />`,
    scope: {
      "stripeComplete": '=',
      "stripeFormId": '@',
      "stripeError": '=',
      "stripeToken": '=',
    },
    link: function(scope, element, attrs) {

      //Init
      var stripe = Stripe("pk_test_6pRNASCoBOKtIshFeQd4XMUh");
      var elements = stripe.elements();
      var card = elements.create("card");
      var form = document.getElementById(scope.stripeFormId);

      //mount card element https://stripe.com/docs/stripe-js/reference#element-mount
      card.mount("#card-element");

      //add event listener
      card.addEventListener('change', function(event) {

        //check for errors
        if (event.error) {
          scope.ccErrMsg = event.error.message;
        } else {
          scope.ccErrMsg = '';
        }

        //check for complete
        scope.stripeComplete = event.complete ? true : false;

        //apply scope
        scope.$apply();
      });

      //inject form submit event
      form.addEventListener("submit", function(event) {

        //prevent form submit
        event.preventDefault();

        //handle token, handle error and form submit forward
        stripe.createToken(card).then(function(result) {

          if (result.error) {
             scope.ccErrMsg = event.error.message;
             scope.stripeToken = '';
          } else {
             scope.ccErrMsg = '';
             scope.stripeToken = result.token;
          }

          //apply scope
          scope.$apply();

          //forward submit
          form.submit();
        })
      });
    }
  }
});

我想使用form.submit()将表单参数和数据发送到我的后端,然后在$http.post()函数中从那里发回任何数据,而不是使用.then()。在这种情况下,参数包括reg.email的值。

我如何设置表单的方式?我更喜欢使用ng-submit,但如果那不可能,还有另外一种方法吗?

javascript angularjs stripe-payments
1个回答
1
投票

我建议使用component来包装条纹输入。您可以使用ng-model指令使此组件工作,以将卡元素传递回父作用域,并将表单验证应用于条带字段。

TL; DR - Here's an example Fiddle

您要做的第一件事是将条带对象创建为服务,以便共享。

app.service('stripe', function () {
    return Stripe("pk_test_6pRNASCoBOKtIshFeQd4XMUh");
});

然后,您可以实现条带component来环绕条带输入并应用自定义ng-model验证。

app.component('stripe', {
    bindings: {
        state: '='
    },
    require: {
        model: 'ngModel'
    },
    controller: function ($element, $timeout, stripe) {
        this.$onInit = function () {
            var ctrl = this;

            // stripe is passed in to controller as a service
            var elements = stripe.elements();
            var card = elements.create('card');
            card.mount($element[0]);

            card.addEventListener('change', function (event) {
                // Attach the event as the state so it is visible
                // to consumers of the stripe component.
                ctrl.state = event;

                // Set the validity of the stripe on the ng-model
                ctrl.model.$setValidity('stripe', event.complete);

                // If the stripe is complete set the card element on 
                // the ng-model, otherwise null out the model value.
                if (event.complete) {
                    ctrl.model.$setViewValue(card);
                } else {
                    ctrl.model.$setViewValue(null);
                }
            });
        }
    }
});

然后在主控制器中,您可以在发送表单之前创建条带标记,然后再发送HTTP请求。

app.controller('MainCtrl', function ($scope, $http, stripe) {
    $scope.reg = {};
    $scope.onChange = function() {
        console.log($scope.card);
    };
    $scope.register = function () {
        // Create the stripe token and send the registration
        stripe.createToken($scope.card).then(function (result) {
            if (result.error) {
                console.error(result.error);
            } else {
                $scope.reg.stripeToken = result.token;
                $http.post('request-url', $scope.reg).then(function (response) {
                    console.log(response);
                }).catch(function (err) {
                    console.error(err);
                });
            }
        });
    };
});

现在您只需将stripe元素添加到模板中,如下所示:

<div ng-app="angularjs-starter" ng-controller="MainCtrl">
  <form name="regForm" id="register-form" ng-submit="register()">
    <stripe name="card" ng-model="card" state="cardState" ng-change="onChange()" ng-required="true"></stripe>
    <button ng-disabled="regForm.$invalid">Register</button>
    <span ng-if="regForm.card.$invalid">{{ cardState.error.message }}</span>
  </form>
</div>
© www.soinside.com 2019 - 2024. All rights reserved.