Here’s a recipe for how to make a nice AJAX-based email-subscribe form for MailChimp with Angular. Documentation and examples are light around jsonp with Angular, and Mailchimp has no docs around it’s jsonp endpoint that I know of. It took too much of my time, so here’s what I learned.

First, create your list. Select it, then go to signup forms > embedded forms > naked. The generated code gives you 2 things: A form endpoint and the input names you should use.

Note: If you are thinking of using the MailChimp API, don’t bother. There is an important caveat that’s buried in their docs:

“MailChimp does not support client-side implementation of our API using CORS requests due to the potential security risk of exposing account API keys.”

Thankfully we can leverage jsonp for our subscribe form. But your form endpoint that you grabbed from the generated code needs to be modified to support jsonp. You will start with something like this:

https://username.us6.list-manage.com/subscribe/post?u=abc123&id=f4900372db

Change the endpoint from /subscribe/post to /subscribe/post-json:

https://username.us6.list-manage.com/subscribe/post-json?u=abc123&id=f4900372db

This exposes another query string param, “c” for the jsonp callback, we’ll circle back to that.

In app.module.ts, make sure HttpClientJsonpModule is imported along with the HttpClientModule:

import { HttpClientModule, HttpClientJsonpModule } from '@angular/common/http';
@NgModule({
  imports: [
    HttpClientModule,
    HttpClientJsonpModule,
    ...
  ],
  ...
})

Angular Component Inputs for Your Signup Form

Make a component that holds the actual email signup form. I won’t cover making a form in this article, but here are the important points for your form: use (ngSubmit) to submit the form, and therefore omit the action and method attributes found in the generated form code.

Your input name attributes should match the names given in the generated code. They are typically all caps. Also, notice there is also a hidden input with a tokenized name. We’ll need that as well. Your form component will look something like this:

import { Component } from '@angular/core';
import { FormControl, Validators } from '@angular/forms';
import { HttpClient, HttpParams } from '@angular/common/http';

interface MailChimpResponse {
  result: string;
  msg: string;
}

@Component({
 selector: 'email-subscribe-form',
 templateUrl: './email-subscribe-form.component.html'
})
export class EmailSubscribeForm {

 submitted = false;
 mailChimpEndpoint = 'https://username.us6.list-manage.com/subscribe/post-json?u=abc123&id=123&';
 error = '';

 constructor(private http: HttpClient) { }

  // reactive form components
 emailControl = new FormControl('', [
  Validators.required,
  Validators.email,
 ]);
 nameControl = new FormControl('', [
  Validators.required
 ]);

 submit() {
  this.error = '';
  if (this.emailControl.status === 'VALID' && this.nameControl.status === 'VALID') {

   const params = new HttpParams()
    .set('NAME', this.nameControl.value)
    .set('EMAIL', this.emailControl.value)
    .set('b_123abc123abc123abc123abc123abc123abc', ''); // hidden input name

   const mailChimpUrl = this.mailChimpEndpoint + params.toString();

      // 'c' refers to the jsonp callback param key. This is specific to Mailchimp
   this.http.jsonp,[object Object]

This component uses a Reactive Form, but if you used a template-driven form the only difference will be how you access your input values. We used HttpParams to serialize our form data.

The juicy part here is the call to http.jsonp(). Notice we are typing the response to <MailChimpResponse> which we defined an interface for at the top. The first argument is the url with url-encoded params, and the second argument is the value of the jsonp callback param key.

If you test your form you will notice that angular uses this value to append the jsonp callback key-value pair in the actual request. In the case of MailChimp, the callback is keyed under “c” which we specified in the call to http.jsonp(). It will be at the end of the url:

&c=ng_jsonp_callback_0

There you have it. You can use the error property of your component to display any errors that come back from MailChimp. The submitted property can be used to show a success message.

Happy coding.