Performing a simulated form submission using Angular HttpClient and then redirecting the user after

My current issue involves performing a form POST to a 3rd party payment provider using Angular TypeScript and then redirecting to their hosted payment page. When I submit a standard form via a regular HTML page, the redirection happens automatically. However, when using HttpClient.post in Angular, the redirect does not occur.

I have explored observables and injectors in an attempt to find a solution, but so far nothing has addressed this specific problem. I have come across various Angular version-related problems and solutions during my research, which may have caused me to overlook a simple answer.

I am avoiding using a hidden form with hidden fields because I will need to replicate this process in a mobile (Ionic) app later on. I plan to use their built-in HttpClient along with the standard HttpClient for regular web pages.

import { Component, OnInit } from '@angular/core';
import { HttpClient, HttpHeaders } from '@angular/common/http';

@Component({
  selector    :  'app-paymenttest-page',
  templateUrl :  'paymenttest.page.html',
  styleUrls   : ['paymenttest.page.scss']
})
export class PaymentTestPage implements OnInit {

  constructor(private  http : HttpClient) {
  }

  private void makePayment(url: str, formData: FormData): void {
    let headers = new HttpHeaders({'Accept' : 'text/html' });

    this.http.post(url, formData, {
      headers         : headers,
      responseType    : 'text',
      })
       .subscribe(
         (res) =>  {
           console.log('post res');
           console.log(res);

           window.location.href = res.url;
    // How do I simulate a form submit redirect with res.body here?
         },
         (err) => {
          console.log('post err');
          console.log(err); 
      });
  }
}

My expectation is to achieve a redirect to the 3rd party hosted page, but instead, I only receive the HTML text response from the 3rd party. This is the same response I get when doing a basic HTML form submit, but the form submit somehow manages the redirect.

-- Edit The response I am receiving is the actual HTML payload from the URL I am posting to and expects to be served from that URL. Therefore, my question is: how does a regular HTML form submit navigate to the POST URL and display the returned content from there?

Answer №1

External URL Redirection

To redirect to an external URL in Angular, you need to import the DOCUMENT module.

import { DOCUMENT } from '@angular/common';
import { Inject, Injectable } from '@angular/core';

...
constructor(@Inject(DOCUMENT) private document: any) { }

...
this.http.post(url, formData, { headers: headers, responseType: 'text'}).subscribe(
  (res) => {
    console.log('post res');
    console.log(res);

    this.document.location.href = res.url;
  },
  (err) => {
    console.log('post err');
    console.log(err); 
   });
  }
}

Dynamic HTML Injection

If you need to dynamically inject HTML content into your Angular template, you can use the DomSanitizer to ensure security.

data: SafeHtml;

constructor(private sanitizer: DomSanitizer) {}      

ngOnInit(){ 
    this.http.post(url, formData, { headers: headers, responseType: 'text'}).subscribe(
    (res) =>  {
      console.log('post res');
      console.log(res);
      
      this.data = this.sanitizer.sanitize(res.html);
            /* OR */
      this.data = this.sanitizer.bypassSecurityTrustHtml(res.html);
  },
  (err) => {
    console.log('post err');
    console.log(err); 
   });
  }
}

To display the injected HTML in your template:

<div>
  <div [innerHtml]="data"></div>
</div>

Answer №2

I finally managed to make it work by creating an HTML page with a hidden form and rewriting the document. This method works flawlessly for both standard Angular pages and Ionic. Below is the TypeScript code I used to achieve this:

private _providerPayment(vpp: bVoucherPaymentPayload): void {
    let pageContent = '<html><head></head><body><form id="payForm" action="' + vpp.endpoint + '" method="POST">';

    for (let item of vpp.formFields) {
      let ff: bLookupItem = (<bLookupItem> item);
      pageContent += '\n  <input type="hidden" name="' + ff.key + '" value="' + ff.value + '">';
    }

    pageContent += '\n</form><script type="text/javascript">document.getElementById("payForm").submit();</script></body></html>';

    // console.log('DYNAMIC FORM!!');
    // console.log(pageContent);

    if (this._runningOnNativeDevice()) {
      const pageContentUrl = 'data:text/html;base64,' + btoa(pageContent);      

      this._inAppBrowser.create(pageContentUrl, "_self", {
       'location'          : 'no',
       'presentationstyle' : 'fullscreen',
      });
    } else {
      document.open();
      document.write(pageContent);
      document.close();
    }
  }

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Video showcasing issue with updating Ionic2 view

I am encountering an issue where my View is not updating as expected. When a player makes a move, the triggers work (I did a console log on every update of the current game [1]), but the View does not update regularly. To investigate this problem, I added ...

The absence of a `require` definition in Typescript combined with daisyui

Considering using typescript with react and daisyUI (a tailwindCSS component). Just a heads up, I'm currently utilizing vite In my ts.config file, I've specified node as moduleResolution Encountering an error in the tailwind config stating &apo ...

Implementing various custom validators in Angular 2 reactive forms

I am facing an issue with two custom validator functions in a reactive form. I have the following function that creates the form within the component constructor: private createForm(): void { this.passwordUpdateForm = this.formBuilder.group({ newpassw ...

"Encountering a Cypress Angular error: CypressError with the message 'Timed out retrying: Expected content was not

During my Cypress test run, I encountered an error message on the last step (click) which stated: Timed out retrying: Expected to find element: .button-darkblue, but never found it. Here is the code snippet: describe('Test Login', () => { i ...

Neglect certain concealed fields on AG Grid for now

Currently, I am working with Angular and AG-Grid to create a table below. By default, the table looks like this: https://i.sstatic.net/J3wkn.png However, when a user hovers over a row, two hidden buttons will appear as shown here: https://i.sstatic.net/D ...

Storing the compiled TypeScript file in the source file's directory with the TypeScript compiler

I am in need of assistance with compiling TypeScript files (ts) into JavaScript files (js) and mapping files (js.map) all within the same directory as the source file. I have attempted to configure this in my tsconfig.json file using: { "compilerOption ...

Is there a feature similar to notifyWhenNoOutstandingRequests in Angular 2?

In my experience, test frameworks like Arquillian have utilized this method to determine when the DOM is ready for inspection with Angular 1. I am curious if there is a similar approach for accomplishing this in Angular 2? ...

Reducing file size when uploading images in Angular4 through image compression

saveImage(event: any, type, image_type) { this.uploadImageFlag = true; const fileList: FileList = event.target.files; if (fileList.length > 0) { const file: File = fileList[0] this.files.set('files', file, file.name) ...

What is the best way to link three different types of http requests in succession and adaptively?

Is it possible to chain together 3 types of http requests correctly, where each request depends on data from the previous one and the number of required requests can vary? In my database, there is a team table with a corresponding businessId, a supervisor ...

Angular 2 regex for validating FQDN/URL formats

As a beginner in regex, I'm looking for help with validating fully qualified domain names (e.g. mysite.com) or a URL without checking the protocol. Can anyone provide a regex expression or suggest where to find one? ...

Error message: The object is not visible due to the removal of .shading in THREE.MeshPhongMaterial by three-mtl-loader

Yesterday I posted a question on StackOverflow about an issue with my code (Uncaught TypeError: THREE.MTLLoader is not a constructor 2.0). Initially, I thought I had solved the problem but now new questions have surfaced: Even though I have installed &apo ...

Discovering the type of a generic class in TypeScript

Class B extends a generic class A, and I am trying to infer the generic type of A that B is extending. The code snippet below demonstrates this. In earlier versions of TypeScript, this worked correctly for me. However, in my current project using version ...

What is the best way to make an Angular Material checkbox respond to a programmatic change in value within a reactive form?

I have implemented a dynamic angular form that allows users to add rows using a button. I am currently working on adding functionality to select all rows. Each row includes a checkbox that toggles the value in the object between T and F. If all checkboxes ...

Issue with Angular material tabs not displaying the first tab when navigating to different outlets

After defining the routes as indicated below, I encountered an issue when a user loads the application using the URL --> http://localhost:4200/will-kit. It seems that only the TABS are displayed and the first tab is not loaded by default. https://i.sta ...

What is the correct way to access $auth in Nuxt with TypeScript?

<script lang="ts"> import LoginAdmin from '@/components/LoginAdmin.vue' import { Component, Vue } from 'nuxt-property-decorator' import Auth from "@nuxtjs/auth"; export default class MyStore extends Vue { pub ...

React 18 Fragment expressing concern about an excessive amount of offspring

Recently, I attempted to integrate Storybook into my React application, and it caused a major disruption. Despite restoring from a backup, the absence of the node_modules folder led to issues when trying 'npm install' to recover. Currently, Types ...

Tips for Observing angular forkJoin for multiple responses during unit testing with Jasmine

Currently, I am focusing on unit testing and I have a function that makes multiple API calls simultaneously. Although I have used spyOn on the service function, I am facing difficulty in returning multiple responses. Can anyone provide guidance on where I ...

Using only HTML, I have created a collapsible accordion in Angular without the need for JS code. However, when I click the button, nothing happens. Can you help me resolve

I am attempting to add an Accordion button to my website using the HTML code provided below. I am currently incorporating this in a very basic manner, without any utilization of javascript code, within this example of accordion snippet. When the button i ...

The browser is sending numerous requests for the audio tag

I am facing an issue with an audio tag in my code. The URL is being parsed and returned by a function. <audio class="fr-draggable" controls autoplay [src]="extractAudioUrl(message)" style="width:100%"></audio> Unfortunately, the browser ends ...

updating a value in a svelte writable store using cypress

Inside my Svelte application, I am working with a boolean variable. import { writable } from 'svelte/store' export const authorised = writable(false) This variable is imported into App.svelte and other Svelte files, where it can be accessed and ...