vanilla js with rxjs : autocomplete search

I’m trying to use rxjs with vanillajs to implement an autocomplete functionality.

I created an index.html page containing input text and index.js to handle “keyup” event and send request to the server .As it is just a demonstration, I used a json-server library to mock the API .

What I want is as the user put characters, the server send API request only if the character is not the same as the previous request

For example, if he puts: “Ev” a request is sent, then he deletes “v” then puts again that “v” the server doesn’t send a request to the server again, since it has been sent for “Ev” .

To do that I used distinctUntilChanged() like the code below but it does not work (The API works fine).

import { debounceTime, map, distinctUntilChanged } from "rxjs/operators";
import { fromEvent } from "rxjs";
const url = "http://localhost:3000/clubs?q=";
let inputTxt = document.getElementById("text-input");
let textChange$ = fromEvent(inputTxt, "keyup");
let autoSuggest$ = textChange$.pipe(
  debounceTime(1000),
  distinctUntilChanged((prev, curr) => prev.target.value == curr.target.value),

  map((e) => fetch(url + e.target.value).then((response) => response.json()))
);
 

And this is the HTML

<body>
    <input
      type="text"
      class="form-control"
      placeholder="Search"
      id="text-input"
    />

    <script src="./index.js"></script>
  </body>

Answer

This is not comparing the target element in the previous state, just the previous event object. target is still a reference to the same element, so the value is always the same:

distinctUntilChanged((prev, curr) => prev.target.value == curr.target.value),

Instead, you can use map to store the value before comparison:

let inputTxt = document.getElementById("text-input");
let textChange$ = fromEvent(inputTxt, "keyup");

let autoSuggest$ = textChange$
  .pipe(
    map(e => e.target.value), // Extract value here
    debounceTime(1000),
    distinctUntilChanged(),
    mergeMap(value => fetch(url + value).then((response) => response.json()))
  )

Leave a Reply

Your email address will not be published. Required fields are marked *