HttpClient POST request using x-www-form-urlencoded

You're posting JSON data to the API instead of form data. The snippet below should work.

login(username, password): Observable<any> {
  const body = new HttpParams()
    .set('username', username)
    .set('password', password);

  return this.http.post('/login',
    body.toString(),
    {
      headers: new HttpHeaders()
        .set('Content-Type', 'application/x-www-form-urlencoded')
    }
  );
}

There is an easier way than the others approaches described here.

This is what worked for me with Angular 7:

const payload = new HttpParams()
  .set('username', username)
  .set('password', password);

this.http.post(url, payload);

No need to explicitly set the header with this approach.

Note that the HttpParams object is immutable. So doing something like the following won't work, it will give you an empty body:

const payload = new HttpParams();
payload.set('username', username);
payload.set('password', password);

this.http.post(url, payload);

You can as well as load your data from an object

login(username, password): Observable<any> {
    const body = new HttpParams({
        fromObject: {
            username,
            password,
            ...extraData, // if any 
        }
    });

    return this.http.post('/login',
        body.toString(),
        {
            headers: new HttpHeaders()
                .set('Content-Type', 'application/x-www-form-urlencoded')
        }
    );
}