1

I have a array named selectedItems that is populated from a multi-select dropdown button. SelectedItems could looks like this if all options were selected:

this.selectedItems: SearchItem[]= [
  {"id":"abee232","itemName":"Attractions"},
  {"id":"b6b1a23","itemName":"Artists"},
  {"id":"08a58c8","itemName":"Performing Arts"},
  {"id":"444d047","itemName":"Sports"}
];

I need to add the id values, however many have been selected, as parameters in a http GET request. Right now my logic looks like this.

  private addRequestOptions(params: SearchItem[]): RequestOptions {
    let options: RequestOptions = new RequestOptions();
      options.params = new URLSearchParams();
    if (params != null) params.forEach((p: SearchItem) => {
      options.params.append("&collectionId", p.id);
    })
    console.log(options)
    return options;
  }

  sortResults(){
        let options: RequestOptions = this.addRequestOptions(this.selectedItems);
        this.pendingCardsService.collectionUuidUrl = 'http://address/cards/topbrands?perPage=25', options;
        this.pendingCardsBrandCollection();
  }

With my SearchItem interface looking like this:

export interface SearchItem {
  id?: string;
  itemName?: string;
}

Right now this creates a requestOptions object that has the values in it as an array but my http requests do not show this in the query string parameters field within the network tab. It seems that the addRequestOptions() is working correctly but not being applied properly to the get request. The goal is to end up with a URL something like this:

'http://address/cards/topbrand?perpage=25&collectionId=idValue&collectionId=idValue&collectionId=idValue'

I am stuck how to accomplish this. Any help/tips/suggestions would be much appreciated.

UPDATE w/final code My issue was with me having hard coded in 'http://address/cards/topbrands?perPage=25' ?perPage=25 was being read as params (rightfully so) and therefore the addition of the ids were not being appended since params were already present. My final code ended up looking like this that got it working properly:

  fetchPendingCardsBrandCollection(ids: SearchItem[], pageSize = '25'):Observable<Card[]> {
    const params = new URLSearchParams();
    params.set('perPage', pageSize);
    ids.forEach(id => params.append('collectionId', id.id));
    return this.http.get(this.collectionUuidUrl, {params: params})
      .map(this.extractData)
  }

With my function calling this http request function passing SearchItems as a parameter. Big thanks for @Praveen M for the assistance and @Jota.Toledo for the solution!

Brian Stanley
  • 2,078
  • 5
  • 24
  • 43

2 Answers2

1
import { Observable } from 'rxjs/Observable';
import { Injectable } from '@angular/core';
import { Http, URLSearchParams } from '@angular/http';

export interface SomeInterface {
   // Define the properties of the JSON object sent as response from the backend
}

@Injectable()
export class SomeService {
   constructor(private _http: Http){}

   queryElements(ids: string[] = [], pageSize = 25): Observable<SomeInterface>{
      const params = new URLSearchParams();
      params.set('perPage', pageSize); // using set: replace the existing value of the query parameter "perPage" if exist.
      ids.forEach(id => params.append('collectionId', id)); // using append: allows multiple values for the query parameter "collectionId" 
      return 
       this._http.get("http://address/cards/topbrand",{params: params})
         .map(r => r.json())
         .catch(//handle error);
   }
}
Jota.Toledo
  • 27,293
  • 11
  • 59
  • 73
-1

Update the existing array of data by giving it a type so there is less wiggle room for error when dealing with the array.

// Add the class to a ts file
export class Args {
 id: string;
 itemName: strngs;
}

dropdownList: Args[] = [];

// Declare the selectedItems is a type of Args class
selectedItems: Args[] = [];


this.dropdownList = [
  {id:"abee232b6f3b06c3da1955fb270ced28", itemName:"Attractions"},
  {id:"b6b1a23b6a0ad3ab467284ca92bc7d59", itemName:"Artists"},
  {id:"08a58c804fa4eb462ad4e690a51864f6", itemName:"Performing Arts"},
  {id:"444d0472d7d94f569da6fd7a5608faba", itemName:"Sports"}
];

// Now they are actual key value pair
this.selectedItems = [
  {id:"abee232",itemName:"Attractions"},
  {id:"b6b1a23",itemName:"Artists"},
  {id:"08a58c8",itemName:"Performing Arts"},
  {id:"444d047",itemName:"Sports"}
];

//CSV Format

private addRequestOptions(params: Args[]): RequestOptions {
  let options: RequestOptions = new RequestOptions();
  let list: string = "";
  options.params = new URLSearchParams();
  if (params != null) params.forEach((p: Args) => {
    list + p.id + ",";
  });
  options.params.set("collectionId", list);
  console.log(options);
  return options;
}

// Array of parameters format

private addRequestOptions(params: Args[]): RequestOptions {
  let options: RequestOptions = new RequestOptions();
  let list: string = "";
  options.params = new URLSearchParams();
  if (params != null) params.forEach((p: Args) => {
    options.params.append("collectionId", p.id);
  });
  console.log(options);
  return options;
}

This will create a RequestOptions for the paramenters you passed as agrs to it and you can plug it straight in the the Get method.

this.http.get(url, this.addRequestOptions(this.selectedItems))
  .map((res: any) => res.json() as any)
  .catch((err: Response) Observable.throw(console.log(err)));

import {Http, RequestOptions, URLSearchParams} from "@angular/http";
import "rxjs";
import {Observable} from "rxjs/Observable";

UPDATE Now you should be able to pass the selectedItems variable in as the addRequestOptions argument and it will produce url parameres for the all the ids.

This post shows few ways of you could pass the values as Array of parameters

Prav
  • 2,785
  • 1
  • 21
  • 30
  • That should produce something like `http://address/cards/topbrand?perpage=25collectionId=id1,id2,id2,id4.....` – Prav Jul 24 '17 at 21:21
  • A lot of back end frameworks have built in support to parse key=value1&key=value2 into an array with no extra code. By using the coma approach, you need to create a parser method. – Jota.Toledo Jul 24 '17 at 21:28
  • @Jota.Toledo Thanks for pointing that out, I wasn't sure if I should use that method. I have updated the code with both options now – Prav Jul 24 '17 at 21:34
  • You still have in your answer "at least its not best practice". Where did you got that from? And btw, https://stackoverflow.com/questions/42376972/best-way-to-import-observable-from-rxjs . Im pretty sure import "rxjs" either does nothing or does "way to much" ;) – Jota.Toledo Jul 24 '17 at 21:37
  • I removed the best practice part and I added the `rxjs` if the user decided to use other functionalities of it other that `Observable`. Its up to the user to include it or not. I.E `BehaviorSubject` – Prav Jul 24 '17 at 21:44
  • Trust me on that one, you dont want to use import 'rxjs' – Jota.Toledo Jul 24 '17 at 21:54
  • So if i am understanding this correctly the this.addRequestOptions(args[]), my arguments are the this.searchItem which simply contains the ids of the selected items. I tried something like this but didn't get it working. this.addRequestOptions(this.searchItem[this.searchItem.id]) – Brian Stanley Jul 25 '17 at 15:14
  • @BrianStanley Thats because number of parameters in the array are wrong. I have updated the code with a actual `key-value` pair. Try that one – Prav Jul 25 '17 at 17:41
  • Won't that conflict with params: string[]? Also for my use selectedItems is an empty array that stores the selected options from the dropdown button. I do have a dropdownList [] that is defined with key:value pairs of id and item name. Apologies for my confusion – Brian Stanley Jul 25 '17 at 18:49
  • @BrianStanley You have to make sure you pass the same type of infomation to the `addRequestOptions` method as its expecting. So the `selectedItems` you had wasn't mapped properly and the method was expecting an array `id`s not `id`s and their `name`s. So you'll have to pick the id from each array object and map to a new variable that endup with only array of `id`s; which you can pass into the method. Since the my version is using type to control the values it doesn't need all that manual work. So the method knows what's the `id` and `name` are. – Prav Jul 25 '17 at 19:06
  • If you provided with the variable that used in the dropdown list, I could map to a type so its easy on the long run – Prav Jul 25 '17 at 19:09
  • @PraveenM provided the dropdownList in under Update – Brian Stanley Jul 25 '17 at 21:08
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/150199/discussion-between-brian-stanley-and-praveen-m). – Brian Stanley Jul 26 '17 at 13:45