【问题标题】:AngularJS : What's the Angular way to interact with a form?AngularJS:Angular 与表单交互的方式是什么?
【发布时间】:2013-01-21 22:29:53
【问题描述】:

我了解 Angular 的关键原则之一是:

你不能在你的控制器中引用你的 DOM。

我正在尝试处理信用卡付款,这需要以下步骤:

  • 用户填写表单,然后单击提交按钮
  • 该表单的一部分被发送到我们的服务器,从而开始与支付网关的交易
  • 来自我们服务器的响应会更新表单中的值,然后必须通过表单 POST 将其直接提交到支付网关。
  • 发生了其他事情。

在这种情况下,我该怎么做:

  • 更新表单中的数据(不从控制器引用表单)
  • 获取要提交的表单?

表单绑定到我的控制器上的模型,所以我尝试了类似以下的方法:

<form action="{{paymentModel.urlFromTheResponse}}">
    <input type="hidden" name="accessCode" value="{{paymentModelaccessCodeFromResponse}}" />
    <button ng-click="startTransaction(paymentModel)"></button>
</form>

// in my success handler
.success(function(data) {
     paymentModel.urlFromTheResponse = data.url;
     paymentModel.accessCode = data.accessCode;
     $scope.apply();
}

这里的理论是,如果我可以通过数据绑定立即使表单进入正确的状态,那么我可以做一些事情来提交表单。但是,这会引发错误:

正在消化

Angular 支持这种类型的流程的方式是什么?看来我需要直接与 DOM 交互,这违背了控制器的本质。

【问题讨论】:

  • 谁在提交表单——你(通过 JavaScript),还是用户看到更新后的数据?
  • 为了学习,比方说我,通过 Javascript。

标签: angularjs


【解决方案1】:

正如其他人所说,您不需要调用 $scope.$apply() 因为表单应该已经通过在每个字段上设置 ng-model 属性来绑定到角度。

但是,当从 angular 之外的其他来源拉入数据时,有时需要调用 $scope.$apply() 来更新显示...

在这些情况下,我很幸运:

  // This method will be inherited by all other controllers
  // It should be used any time that $scope.$apply() would
  // otherwise be used.
  $scope.safeApply = function(fn) {
    var phase = this.$root.$$phase;
    if(phase == '$apply' || phase == '$digest') {
      if(fn && (typeof(fn) === 'function')) {
        fn();
      }
    } else {
      this.$apply(fn);
    }
  };

我把它放在我最外层的控制器中,所以页面上的所有其他控制器都继承了它的功能。每当我发现我需要调用 apply 时,我都会调用 $scope.safeApply(),它会调用 apply if还没有正在进行的应用或摘要,否则,当前运行的应用/摘要将拾取这些更改。

在你的代码中我会改变这个:

<input type="hidden" name="accessCode" value="{{paymentModelaccessCodeFromResponse}}" />

到这里:

<input type="hidden" name="accessCode" ng-model="paymentModel.accessCode" />

我可能还会删除表单操作,而是在控制器中添加类似这样的内容:

$scope.$watch('paymentModel.accessCode', function() {
  // Fire off additional form submission here.
})

【讨论】:

    【解决方案2】:

    产生错误是因为你的成功回调已经在“Angular 内部”,所以 $scope.apply() 会自动为你调用。

    如果您在表单元素上使用 ng-model(而不是 value),那么您可以在成功回调中修改 model/$scope 属性,表单将自动更新(由于通过 ng-model 进行双向数据绑定)。然而,与其尝试提​​交表单,为什么不直接使用控制器中的 $http 或 $resource 服务来调用 Web 服务呢? (这就是为什么我询问用户是否需要参与我的评论。)

    【讨论】:

      【解决方案3】:

      假设您正在使用 $http 之类的东西,您已经在角度范围内,不需要手动调用 $scope.apply();因为您已经在角度执行中。

      你应该能够放弃 $scope.apply() 并简单地拥有一个

      .success(function(data) {
           paymentModel.urlFromTheResponse = data.url;
           paymentModel.accessCode = data.accessCode;
       $http.post("/finalstep",paymentModel).success(function(data)
      {
      // other stuff
      });
      }
      

      【讨论】:

        猜你喜欢
        • 2020-05-10
        • 1970-01-01
        • 1970-01-01
        • 2011-06-09
        • 2017-06-05
        • 2013-07-03
        • 1970-01-01
        • 1970-01-01
        • 2018-12-23
        相关资源
        最近更新 更多