24

I'm new to Angular2. I have a JSON object, as below:

var options = {
  param1: "parama1",
  param2: "parama2",
  param3: "parama3"
};

which should convert to query string and append to an external URL to redirect the page like below:

ngOnInit(){
     window.location.href = someurl?param1=param1&param2=param2&param3=param3;
}

I'm looking for a way to convert it to query string. In JQuery, $.param() and in AngularJS $httpParamSerializerJQLike() are there for this. I'd searched, but I got nothing. I want to know is there any way to do it in angular2.

4

5 Answers 5

64

A more 'official' method without the string concats:

import {URLSearchParams} from '@angular/http'
let options = {
  param1: "param1",
  param2: "param2",
  param3: "param3"
};

let params = new URLSearchParams();
for(let key in options){
    params.set(key, options[key]) 
}

console.log("http://someUrl?" + params.toString());

This does automatic encoding by the way.

Sign up to request clarification or add additional context in comments.

5 Comments

@sitchie - I rejected your proposed edit. The params are already URLEncoded if you use this method.
I got it, but there is no way to revert.
FYI: Until recently, URLSearchParams needs a polyfill to be used correctly in some browsers (IE and Safari), does anyone know if that changed?
URLSearchParams is now deprecated in favor of HttpParams: angular.io/api/common/http/HttpParams
See my answer bellow how to use HttpParams
10

You can use HttpParams

import { HttpParams } from '@angular/common/http';

new HttpParams({fromObject: yourObject}).toString()

1 Comment

This is the best answer for Angular
8

This solution will work with most complex types

Incase anyone was wondering how to do this, I've written an extension that should work with c# .Net Core 1.1 and Typescript 2.2.2 WebApi which looks like so.

Remember to include these two imports where you are using it as well

import { URLSearchParams } from '@angular/http';
import 'rxjs/add/operator/map'

export class QueryStringBuilder {
    static BuildParametersFromSearch<T>(obj: T): URLSearchParams {
        let params: URLSearchParams = new URLSearchParams();

        if (obj == null)
        {
            return params;
        }

        QueryStringBuilder.PopulateSearchParams(params, '', obj);

        return params;
    }

    private static PopulateArray<T>(params: URLSearchParams, prefix: string, val: Array<T>) {
        for (let index in val) {
            let key = prefix + '[' + index + ']';
            let value: any = val[index];
            QueryStringBuilder.PopulateSearchParams(params, key, value);
        }
    }

    private static PopulateObject<T>(params: URLSearchParams, prefix: string, val: T) {
        const objectKeys = Object.keys(val) as Array<keyof T>;

        if (prefix) {
            prefix = prefix + '.';
        }

        for (let objKey of objectKeys) {

            let value = val[objKey];
            let key = prefix + objKey;

            QueryStringBuilder.PopulateSearchParams(params, key, value);
        }
    }

    private static PopulateSearchParams<T>(params: URLSearchParams, key: string, value: any) {
        if (value instanceof Array) {
            QueryStringBuilder.PopulateArray(params, key, value);
        }
        else if (value instanceof Date) {
            params.set(key, value.toISOString());
        }
        else if (value instanceof Object) {
            QueryStringBuilder.PopulateObject(params, key, value);
        }
        else {
            params.set(key, value.toString());
        }
    }

}

This is working for all the complex types I've used so far.

Edit UrlSearch Parameters has been removed. Here is the updated changes via @NuryagdyMustapayev's gist:

static buildParametersFromSearch<T>(obj: T): HttpParams {
    let params: HttpParams= new HttpParams();

    if (obj == null)
    {
        return params;
    }

    return QueryStringBuilder.populateSearchParams(params, '', obj);
}

private static populateArray<T>(params: HttpParams, prefix: string, val: Array<T>): HttpParams {
    for (let index in val) {
        let key = prefix + '[' + index + ']';
        let value: any = val[index];
        params = QueryStringBuilder.populateSearchParams(params, key, value);
    }
    return params;
}

private static populateObject<T>(params: HttpParams, prefix: string, val: T): HttpParams {
    const objectKeys = Object.keys(val) as Array<keyof T>;

    for (let objKey of objectKeys) {

        let value = val[objKey];
        let key = prefix;
        if (prefix) {
            key += '[' + objKey + ']';
        } else {
            key += objKey;
        }

        params = QueryStringBuilder.populateSearchParams(params, key, value);
    }
    return params;
}

private static populateSearchParams<T>(params: HttpParams, key: string, value: any): HttpParams {
    if (value instanceof Array) {
        return QueryStringBuilder.populateArray(params, key, value);
    }
    else if (value instanceof Date) {
        return params.append(key, value.toISOString());
    }
    else if (value instanceof Object) {
        return QueryStringBuilder.populateObject(params, key, value);
    }
    else if ('undefined' !== typeof value && null !== value){
        return params.append(key, value.toString());
    }
    return params;
}

Remember to import {HttpParams} from "@angular/common/http";

5 Comments

Just as a note you call using the only public method BuildParametersFromSearch
URLSearchParams is removed, HttpParams is used instead. I updated your code to use HttpParams here is the gist: gist.github.com/nuryagdym/9fe9ab4b3de3d5738d6f596ecf5db374
I made a mistake, can you replace || in this line else if ('undefined' !== typeof value || null !== value) with &&, stackoverflow does not let me offer an edit.
Hmm, I changed it but, after reading that, are we sure we want to remove null or undefined values in the first place? Aren't some model binders dependent on the fact that the value has been defined.
It does not remove it, it just returns value as it is if undefined or null. otherwise, I was getting Cannot read property 'toString' of null/undefined error
2

How about this:

ngOnInit(){
    let options = {
      param1: "param1",
      param2: "param2",
      param3: "param3"
    };

    let myQuery = 'http://someurl?'
    for (let entry in options) {
        myQuery += entry + '=' + encodeURIComponent(options[entry]) + '&';
    }

    // remove last '&'
    myQuery = myQuery.substring(0, myQuery.length-1)

    window.location.href = myQuery;
}

myQuery value is ?param1=param1&param2=param2&param3=param3.

5 Comments

encodeURI("param1=param1&param2=param2&param3=param4.com") is giving "param1=param1&param2=param2&param3= param4.com ", it is not encoding url
Are you sure you used the same options? Check this plunker: plnkr.co/edit/VvRr4yZkKu7YHhyvaOlb?p=preview it's working fine there (check app.ts and the console)
just put any url as one param and see the result.
@sitchie param1=param1&param2=param2&param3=param4.com seems properly encoded
0

I prefer to not use any library, you can simply use a map function to create it.

So this is what is use for this case:

const params= {
 param1:"value1",
 param2:"value2",
 param2:"value2",
};

const queryStr = Object.keys(params).map((el)=>( `${el}=${params[el]}` )).join("&");

this is the output: param1=value1&param2=value2

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.