10

I have had a similar problem with Angular 1 so I understand how to implement, only I'm missing the last step.

Just like last time, a guy who did backend for our app accepts requests with type application/x-www-form-urlencoded and just like Angular 1 so does Angular 2 send them with type application/json.

What I did with ng1 was that in config I modified the http provider to run urlencoded over body of each request.

I see in ng2 that there is https://angular.io/docs/ts/latest/api/http/BaseRequestOptions-class.html a BaseRequestOptions class which I supposed is made for exactly this only documentation is a bit not there so I'm not sure how to implement this properly (I'm also new to TypeScript).

How do I provide this so that each of my post and other requests get send as urlencoded at the end (I also want the function to be run on the body so that it actually becomes urlencoded).

Also: Why isn't there a simpler option for this since by now I can see that both ASP.Net and Flask (so I suppose many others as well) do not support application\json by default?

EDIT: I have made a custom function which I use on every object I send in POST body but I hope that there is a simpler, more general solution.

import { URLSearchParams } from 'angular2/http';

export function urlEncode(obj: Object): string {
    let urlSearchParams = new URLSearchParams();
    for (let key in obj) {
        urlSearchParams.append(key, obj[key]);
    }
    return urlSearchParams.toString();
}

and then I use it like

this.http.post('http://localhost:5000/user/auth/login', urlEncode(data))
ditoslav
  • 4,563
  • 10
  • 47
  • 79

1 Answers1

12

Try something like this:

DefaultRequestOptions.ts

@Injectable()
export class DefaultRequestOptions extends BaseRequestOptions{
    headers:Headers = new Headers({
        'Content-Type': 'application/x-www-form-urlencoded'
    });
}

boot.ts

bootstrap(AppComponent,[
    HTTP_PROVIDERS,
    provide( RequestOptions, { useClass: DefaultRequestOptions } ),
    provide(Http, { useFactory:
        function(backend, defaultOptions) {
            return new Http(backend, defaultOptions); },
        deps: [XHRBackend, RequestOptions]})
]);

IMPORTANT: Make sure you don't declare HTTP_PROVIDERS again in the component where you'll use the Http object or it'll override the one you are injecting in boot.ts.


For the other function you can just add it into any @Injectable object, add that object into the constructor of your components and you can call it that way from any component, or you can try to extend the http angular object and override the post method in order to do it for every post request behind the scenes.

Langley
  • 5,326
  • 2
  • 26
  • 42
  • This seems like exactly what I need. Could you please also provide how to make it use body = encodeURI(body)? Is it just this.body = encodeURI(this.body) ? – ditoslav Jan 10 '16 at 11:43
  • How do I make a request after this? It seems that when I make a normal http.post this does not get triggered – ditoslav Jan 10 '16 at 12:51
  • are you using the angular2's http module? – Langley Jan 10 '16 at 13:01
  • Yes. I'm using the http to make a post request like this.http.post('http://localhost:5000/user/auth/login', { 'email': this.emailModel, 'password': this.passwordModel }) – ditoslav Jan 10 '16 at 13:09
  • I updated the answer, I already tested it and it works. Check the following sources if you still have issues: [BaseRequestOptions](https://angular.io/docs/ts/latest/api/http/BaseRequestOptions-class.html) [HTTP_PROVIDERS](https://angular.io/docs/ts/latest/api/http/HTTP_PROVIDERS-let.html) - [Headers](https://angular.io/docs/ts/latest/api/http/Headers-class.html) - – Langley Jan 10 '16 at 17:25
  • Are you sure this urlencodes the body? I have created a custom urlEncode function which I use on every object I send to post like: (see EDIT) – ditoslav Jan 10 '16 at 18:29
  • No I don't think so, remember Angular is still in Beta I dont think it does that many things automatically, but you can certainly test it, all this does it set the header that specifies that the content you are sending is application/x-www-form-urlencoded so the guy who did your backend accepts the requests. If you want to add that functionality as well maybe you can extend the Http class and override the post method, and encode the body in there and you instantiate your class instead of the Http one in the example. – Langley Jan 10 '16 at 18:42
  • Yeah I tried doing something like implementing my own http but I don't get dep injection so well so I had some issues when trying to make my http injectable. Thanks! – ditoslav Jan 10 '16 at 19:00
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/100307/discussion-between-dominikditoivosevic-and-langley). – ditoslav Jan 10 '16 at 19:25
  • I moved the extra info of your question from my answer into the question itself and updated my answer to include info about that functionality as well. – Langley Jan 10 '16 at 23:54
  • @Langley awesome answer! Extending the `HTTP` class is a killer feature to plug interceptors... Will be very helpful ;-) – Thierry Templier Jan 22 '16 at 09:52
  • Thank you @ThierryTemplier =) – Langley Jan 22 '16 at 15:09
  • @Langley I get an error cannot find name provide.. is there an import i am missing? – Piotr Stulinski Aug 02 '16 at 11:51
  • I dont think so, they changed the implementation of the http module in one of the rcs, these exact code might not work anymore, youll probable have to change it a bit – Langley Aug 02 '16 at 13:23