1

Application

A simple Search bar and a button where user enters a keyword and the response returned is from a RESTful server (HTTP GET requests)

simplesearch.ts

export class SimpleSearch {
    kw: string; // keyword
    resp: string; // response from Server
}

simplesearch.service.ts

Has a simple method called searchData which does a HTTP GET request with the user's keyword as a query search. (Code not included for brevity)

simplesearch.component.ts

/*All respective headers and @Component removed from brevity*/
const OUTPUT: SimpleSearch[] = []; // create an array for storing Objects

export class SimpleSearchComponent {
    Output = OUTPUT; // define variable for array
    constructor(private httpServ: SimpleSearchService, private temp: SimpleSearch) {}

/*Search button on HTML file does this*/
Search(inputVal: string) {
    this.temp.kw = inputVal; // store the value of user's input
    this.httpServ.searchData(inputVal)
          .then(res => this.temp.resp = res); // store the response in temp.resp

    // push the Object on the Output Array
    this.Output.push({kw: this.temp.kw, resp: this.temp.resp}); 
    }
}

Interpolation Variable

I use Output as an Interpolation Variable for my HTML template. I show the data in an unordered list

<ul>
     <li *ngFor="let keyword of Output">
         <span>{{keyword.kw}}</span>
     </li>
</ul>

 Response:
 <ul>
     <li *ngFor="let answer of Output">
        <span>{{answer.resp}}</span> <!-- WHAT TO DO HERE for Array Index-->
     </li>
 </ul>

Result

I can see the keywords in a list every time a user inputs new keywords but the responses in the wrong way

How do I pass Indexing with the Interpolation? Or am I thinking wrong?

The easy way out was to create two separate Array<String> for keywords and responses and this works great since I can use the index to delete the contents on the page too but with an Object in an Array I am confused with the key: value representation and the index of the Array (OUTPUT) itself.

4
  • 1
    I'm not sure if I understood your question.. however for this statement: "How do I pass Indexing with the Interpolation? Or am I thinking wrong?" You can simply do this: <li *ngFor="let keyword of Output; i as index"> Index: {{i}}. Commented Jun 9, 2017 at 20:02
  • @developer033 I get a delay of one response in the last list. Can I do something like {{answer[i].resp}} in my loop? Commented Jun 9, 2017 at 20:10
  • What do you mean by "last list"? I just can see you iterating the same list 2 times... Also I just found a problem in your code.. you're trying to access this.temp.resp outside the async function (so it's probably undefined). Commented Jun 9, 2017 at 20:15
  • The one under Response I start with an empty bullet point and when I query again the older response is displayed not the new one. Commented Jun 9, 2017 at 20:20

1 Answer 1

1

The problem lies exactly where developer noticed, this.temp.resp is outside the async function. So when you are pushing items in your Output array, it's always pushing the previous search with the new keyword, therefore you are getting the behavior that the resp is always "one step behind". You can check this to understand this async behavior: How do I return the response from an Observable/http/async call in angular2?

So let's look at the code and explain what is happening. I assume you have initialized 'temp' since it isn't throwing an error on first search, where temp.resp would be undefined unless temp is initialized.

this.httpServ.searchData(inputVal)
  // this takes some time to execute, so the code below this is executed before 'this.temp.resp' has received a (new) value.
  .then(res => this.temp.resp = res);

// old value of 'temp.resp' will be pushed, or if it's a first search, empty value will be pushed
this.Output.push({kw: this.temp.kw, resp: this.temp.resp}); 

So how to solve this, would be to move the this.Output.push(... line inside the callback (then), so that the correct values will be pushed to the array.

Also I'd change your model to be an Interface instead of Class. But as to how to change the function and do the assignment inside the callback, I'd also shorten the code a bit and do:

Search(inputVal: string) {
  this.httpServ.searchData(inputVal)
    .then(res => {
       // we are pushing values inside callback now, so we have correct values! 
       // and 'SimpleSearch' stands for the interface
       this.Output.push(<SimpleSearch>{kw: inputVal, resp: res}); 
    });
  }
}

This should take care of it that the corresponding keyword will have the corresponding response! :)

PS. Worth noticing here, is that you'd maybe want to display the keyword while we are waiting for the response for that keyword, I ignored it here though and applied the same as you are currently using.

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

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.