【问题标题】:Angular 2 - Updating hidden form fields and then POSTing to external pageAngular 2 - 更新隐藏的表单字段,然后发布到外部页面
【发布时间】:2017-05-28 16:00:46
【问题描述】:

我有一个 Angular2 应用程序,它有时需要通过 POST 请求将用户发送到外部服务上的页面。

基本上流程应该如下

  • 用户点击按钮
  • 默认表单提交事件被拦截并阻止
  • 执行 API 调用以在后端设置一些内容并检索一些值以传递给外部服务
  • 一些隐藏的表单字段填充了从 API 检索到的数据
  • 然后触发表单提交

据我从 this one 之类的帖子中可以确定,没有办法在 Angular 中执行“POST 到外部页面”类型的操作,而必须使用 ngNoForm 覆盖 Angular 的表单处理并允许浏览器将其作为常规 POST 处理。

所以,目前,我有一个这样的模板:

<form ngNoForm (submit)="proceedToService($event)" method="POST" action="https://some-service.com/etc">
 <input type="hidden" name="token" [value]="someToken">
 <button type="submit">Proceed to external service</button>
</form>

在组件中我有这个:

public someToken:string="";

proceedToService($event) {
    $event.preventDefault();
    this.apiHandler.doSomeStuff().subscribe(
        (someStuff) => {
            this.someToken = someStuff.token;
            $event.target.submit();
        }
    );
}

doSomeStuff 返回一个 Observable)

这种方法的问题是提交事件似乎在值被填充到 DOM 之前被触发,这意味着 token 字段在 POST 请求中为空。

我能够通过将$event.target.submit(); 包装在 setTimeout 调用中来使其工作,如下所示:

setTimeout(() =&gt; {$event.target.submit()}, 1000);

但这感觉像是一种超级 hacky 的方式,无论如何仍然可能失败(如果更新时间超过 1 秒怎么办?)并且很难测试。

那么有没有更好的方法来实现这一点?理想情况下,我想做的是观察隐藏输入的值是否在 DOM 中实际更新,然后在该点触发提交。但到目前为止,我一直无法找到这样做的方法——例如 ngModel 绑定不支持隐藏字段。

我对 Angular 世界,尤其是 Angular2 非常陌生,所以我可能从完全错误的角度来处理这个问题,但我们将不胜感激。

【问题讨论】:

    标签: javascript angularjs forms angular


    【解决方案1】:

    您可以通过使用模板引用变量和 button type="button" 组合来做到这一点。

    <form ngNoForm #extForm method="POST" action="https://some-service.com/etc">  
     <button type="button" (click)="proceedToService(extForm)">External Service</button>
    </form>
    

    打字稿功能

    proceedToService(frm) {
        this.apiHandler.doSomeStuff().subscribe(
          (someStuff) => {        
            var input = document.createElement("input");
            input.type = "hidden";
            input.name = "token";
            input.value = someStuff.token;;
            frm.appendChild(input);
            frm.submit();
          }
        );
      }
    

    希望对你有帮助

    【讨论】:

      【解决方案2】:

      我使用AfterViewChecked 找到了一个潜在的解决方案,如下所示:

      private pendingEvent;
      
      proceedToService($event) {
          $event.preventDefault();
          this.apiHandler.doSomeStuff().subscribe(
              (someStuff) => {
                  this.someToken = someStuff.token;
                  this.pendingEvent = $event;
              }
          );
      }
      
      ngAfterViewChecked() {
          if ( this.pendingEvent ) {
              this.pendingEvent.target.submit();
              this.pendingEvent = null;
          }
      }
      

      这似乎符合我的要求 - 因为在检查视图后调用ngAfterViewChecked,并且在更新视图后检查视图(我假设?)此时值已正确填充。

      在我对 Angular 不熟悉的情况下,我不确定这是否是实践中的最佳解决方案,甚至是可行的解决方案,但它至少“感觉”比使用 setTimeout...

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2017-06-17
        • 1970-01-01
        • 1970-01-01
        • 2011-09-16
        • 2012-03-04
        • 2018-05-08
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多