Dmitry Grinko
Dmitry Grinko

Reputation: 15232

How to pass an array within a query string in HttpClient?

This is my array of actors:

['Elvis', 'Jane', 'Frances']

How to pass this array within a query string in HttpClient?

I tried to use:

1)

let params = new HttpParams();
params = Params.append('actors[]', ['Elvis', 'Jane', 'Frances']);
this.http.get(url, { params: Params });
let params = new HttpParams().set('actors[]', ['Elvis', 'Jane', 'Frances']);
this.http.get(url, { params: Params });
let Params = new HttpParams();
Params = Params.append('actors[]', 'Jane');
Params = Params.append('actors[]', 'Elvis');
Params = Params.append('actors[]', 'Frances');
this.http.get(url, { params: Params }); 

1st and 2nd snippets don't work because of TypeScript error:

[ts] Argument of type 'string[]' is not assignable to parameter of type 'string'.

3rd snippet sends only one item 'actors[]': 'Frances'

Upvotes: 62

Views: 137023

Answers (15)

Bojidari
Bojidari

Reputation: 155

For me it worked as expected by passing the params directly in the options of the request.

const params: HttpParams = new HttpParams().set('attendeeIds', args.attendeeIds.join(','));

        return this.http.get(`/url`,{params});

results in an url that looks like this /url?&attendeeIds=Some-id-1,Some-id-2"

which is not what the server expects

when passing the params directly like below

    return this.http.get(`/url`,{params: {attendeeIds: args.attendeeIds});

the url looks like this /url?&attendeeIds=Some-id-1&attendeeIds=Some-id-2, which is more what the server expects.

hope this helps someone

Upvotes: 0

Sean Chase
Sean Chase

Reputation: 1303

For .NET 7, this works for me:

public async Task<IActionResult> GetItems([FromQuery(Name = "categoryIds")] List<int> categoryIds) {
   ...
}

Then in Angular:

getItems(categoryIds: number[]): Observable<Item[]> {
    const params = new HttpParams({ fromObject: { categoryIds: categoryIds.map(String) } });
    return this.http.get<Item[]>(`${environment.apiUrl}/api/ControllerName/Items`, { params });
}

Upvotes: 0

Gopal B Shimpi
Gopal B Shimpi

Reputation: 139

Try this:

let params = new HttpParams();
let actorList = ['Elvis', 'Jane', 'Frances'];

actorList.forEach((actor: any)=> {
  params = params.append('actors[]', actor);
})

Upvotes: 0

Reza
Reza

Reputation: 177

You can simply do this by using JSON.stringify()

    let params = new HttpParams();
    const actors = ['Elvis', 'Jane', 'Frances'];
    params.append('actors', JSON.stringify(actors);
    this.http.get(url, { params });

Upvotes: 12

Josh England
Josh England

Reputation: 39

Adding this in case anybody comes across it. I was able to override the default behavior, but only by overriding the HttpParams class and utilizing an interceptor. It changes the arrayed-values' parameter name to be appended with the expected '[]'.

class ArrayHttpParams extends HttpParams {
    constructor(options?: any) {
        if (options.cloneParams) {
            const {encoder} : {encoder: HttpUrlEncodingCodec} = options.cloneParams;
            options.encoder = encoder;
        }
        super(options);
        if (options.cloneParams) {
            const {updates, cloneFrom, map} : {updates: any[], cloneFrom: any, map: Map<string, string>} = options.cloneParams;
            (<any>this).updates = updates;
            (<any>this).cloneFrom = cloneFrom || null;
            (<any>this).map = map;
        }
    }
    toString(): string {
        super.toString();
        const {encoder} : {encoder: HttpUrlEncodingCodec} = <any>this;

        return this.keys()
            .map(key => {
                const values = this.getAll(key);
                const encodedKey = encoder.encodeKey(key) + (values.length > 1 ? '[]' : '');

                return values.map(value => encodedKey + '=' + encoder.encodeValue(value)).join('&');
            })
            .filter(param => param !== '')
            .join('&');
    }
}

class MyInterceptor implements HttpInterceptor {
    intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
        let params = null;
        if (req.method === 'GET' && req.params) {
            params = new ArrayHttpParams({cloneParams: req.params});
        }
        req = req.clone({
            setHeaders: headers,
            params: params || req.params
        });

        return next.handle(req);
    }
}

Upvotes: -2

Amir Adabi
Amir Adabi

Reputation: 9

I've used this method and it worked for me in Angular 10:

private paramMaker(data) : HttpParams
{
    let httpParams = new HttpParams();
    Object.keys(data).forEach((key) = > {
        if (Array.isArray(data[key]))
        {
            data[key].forEach((item, index) = > {
                httpParams = httpParams.append(key + '[' + index + ']', item);
            });
        }
        else
        {
            httpParams = httpParams.append(key, data[key]);
        }
    });
    return httpParams;
}

Upvotes: 0

Joe Abdel Sater
Joe Abdel Sater

Reputation: 107

You can do the following:

this.http.get(url, { params: { "actors[]": actorsArray } });

Upvotes: 0

Diego Victor de Jesus
Diego Victor de Jesus

Reputation: 3023

Here is a simple way to do it:

this.http.get(url, { 
    params: ['Elvis', 'Jane', 'Frances'].reduce((accumulator, name) => accumulator.append('names', name), new HttpParams())
});

Upvotes: -1

Geovanny
Geovanny

Reputation: 31

let actorsArray = ['Elvis', 'Jane', 'Frances'];
this.http.get(url, { params: { actors: actorsArray } });

Upvotes: 3

constantant
constantant

Reputation: 1278

According the interface you can do that like

const params = new HttpParams({ 
   fromObject: { 'actors[]': ['Elvis', 'Jane', 'Frances'] } 
});
this.http.get(url, { params });

Upvotes: 24

Venomy
Venomy

Reputation: 2244

I think the best way is to add them to parameters as a string and have your back-end convert it back to an array or list.

let actorList = ['Elvis', 'Jane', 'Frances']
let params = new HttpParams();
params = params.append('actors', actorList.join(', '));
this.http.get(url, { params: params });

Upvotes: 50

Encrust4278
Encrust4278

Reputation: 91

const actors = ['Elvis', 'Jane', 'Frances'];
let params = new HttpParams();
for (const actor of actors) {
  params = params.append('actors', actor);
}

this.http.get(url, { params: params }); 

Upvotes: 7

Ifeanyi Chukwu
Ifeanyi Chukwu

Reputation: 3337

This worked for me.

let params = new HttpParams();

['Elvis', 'Jane', 'Frances'].forEach((actorName:string) =>{
  params = params.append(`actors[]`, actorName);
})

OR

let params = new HttpParams();
let actorsArray:Array<string> = ['Elvis', 'Jane', 'Frances'];

actorsArray.forEach((actorName:string) =>{
  params = params.append(`actors[]`, actorName);
})

Upvotes: 11

Works on Angular 6.0.6:

private getParams(query) {
let params: HttpParams = new HttpParams();
for (const key of Object.keys(query)) {
  if (query[key]) {
    if (query[key] instanceof Array) {
      query[key].forEach((item) => {
        params = params.append(`${key.toString()}[]`, item);
      });
    } else {
      params = params.append(key.toString(), query[key]);
    }
  }
}
return params;

}

Result:

/api/message?page=1&per=2&order_by=name&order_direction=asc&base_object%5B%5D=2&base_object%5B%5D=1

Upvotes: 15

marvstar
marvstar

Reputation: 417

I'm using URLSearchParams instead of HttpParams.

With URLSearchParams you need to stringify your array to set it to your Params "Key-Value-Store".

import { URLSearchParams } from '@angular/http';


let params: URLSearchParams = new URLSearchParams();
params.set('actors', JSON.stringify(yourArrayHere));

I think this should work on the same way with HttpParams because both using a Key-Value mapping in the set method so give it a try.

I hope this can help you.

UPDATE:

let options = new RequestOptions({search: params});

this._http.get(url, options).map(...)

with RequestOptions you can also edit Header and other request options.

Upvotes: 4

Related Questions