Monday, 29 November 2021

How can I delete just one parameter with urlsearchparams.delete()?

So I have an app which displays movies with Movie API and multiple buttons, which show movies of particular genre. So when I click on multiple of such buttons, they all add together in the query, like in the example below:

https://api.themoviedb.org/3/discover/movie?api_key={api_key}&sort_by=popularity.desc&with_genres=99&with_genres=80&with_genres=35

So when I click on one of those genre buttons second time, I want to remove particular genre from url. I tried to do it like this:

function genreChoose(e){
        let genres = {
            Action: 28,
            Adventure: 12,
            Animation: 16,
            Comedy: 35,
            Crime: 80,
            Documentary: 99,
            Drama: 18,
            Family: 10751,
            Fantasy: 14,
            History: 36,
            Horror: 27,
            Music: 10402,
            Mystery: 9648,
            Romance: 10749,
            Science_Fiction: 878,
            TV_Movie: 10770,
            Thriller: 53,
            War: 10752,
            Western: 37
        };
        let url = new URL(lastUrl);
        if(!e.target.classList.contains('active')){
            url.searchParams.append('with_genres', genres[e.target.innerText]);
        }else if(e.target.classList.contains('active')){
            e.target.classList.remove('active');
            url.searchParams.delete('with_genres', genres[e.target.innerText]);
            
        }
        
        fetchURL(url);
        console.log(url);
    }

So if a button is active and is clicked, it should remove 'active' class and also remove particular genre from the url, but instead, it becomes like this:

https://api.themoviedb.org/3/discover/movie?api_key={api_key}&sort_by=popularity.desc

So instead it just removes all 'with_genres' params, but I'm trying to find a way to delete just one of 'with_genres' parameter.

Edit: so I used T.J. Crowder's example, I added a function to remove value:

let url = new URL(lastUrl);
        params = new URLSearchParams(url.search.slice(1));
        console.log(params.toString());
        if(e.target.classList.contains('active')){
            removeValue(params, 'with_genres', genres[e.target.innerText]);
        }else if(!e.target.classList.contains('active')){
            url.searchParams.append('with_genres', genres[e.target.innerText]);
        }
        fetchURL(url);
    }

But it doesn't really remove anything, maybe I should implement it with promises?

Edit 2: So I added a snippet of code, it doesn't display movie blocks sadly, but you can see how url changes when I click genre buttons. So when I click on it, it adds a genre, but when I unclick it, it doesn't remove anything, tho it shows console.log that genre is removed, so I guess it has to do something with removeValue function, but I can't figure out what.

window.onload = function() {
  const API_KEY = 'api_key=73b31f15b44a93f52789c751c34a5d7d';
  const BASE_URL = 'https://api.themoviedb.org/3';
  const API_URL = '/discover/movie?' + API_KEY + '&sort_by=popularity.desc';
  const url = BASE_URL + API_URL;
  const movie_container = document.getElementById('movie_container');
  const prev = document.getElementById('prev');
  const next = document.getElementById('next');
  const ulTag = document.querySelectorAll('.numb');
  const liTag = document.querySelector('li');
  const genres = document.querySelectorAll('.genre');

  var lastUrl = '';
  fetchURL(url);
  
  trendingMovies = movies =>{
        movie_container.innerHTML = '';

        movies.forEach(movie => {
            img = IMG_URL + movie.poster_path;
            title = movie.title;

            const movieEl = document.createElement('div');
            movieEl.classList.add('movie');

            movieEl.innerHTML = 
            `<img src="${img}">
            <span class="movie_title">${title}</span>
                `
            movie_container.appendChild(movieEl);

        });
    }


  function fetchURL(url) {
    lastUrl = url;
    console.log(url);
    fetch(url)
      .then(res => res.json())
      .then(data => {
        trendingMovies(data.results);
        
      })
  }

  
  const removeValue = (params, key, valueToRemove) => {
        const values = params.getAll(key);
        if (values.length) {
            params.delete(key);
            console.log('param deleted', params.toString());
            for (const value of values) {
                if (value !== valueToRemove) {
                    params.append(key, value);
                    console.log('params appended:', params.toString());
                }
            }
        }
        return params; 
    };

    genres.forEach(el => el.addEventListener('click', (e) => {
            genreChoose(e);
            if(e.target.classList.contains('active')){
                e.target.classList.remove('active');
            }else if(!e.target.classList.contains('active')){
                e.target.classList.toggle('active');
            }
            
    }))


    function genreChoose(e){
        let genres = {
            Action: 28,
            Adventure: 12,
            Animation: 16,
            Comedy: 35,
            Crime: 80,
            Documentary: 99,
            Drama: 18,
            Family: 10751,
            Fantasy: 14,
            History: 36,
            Horror: 27,
            Music: 10402,
            Mystery: 9648,
            Romance: 10749,
            Science_Fiction: 878,
            TV_Movie: 10770,
            Thriller: 53,
            War: 10752,
            Western: 37
        };
        let url = new URL(lastUrl);
        params = new URLSearchParams(url.search.slice(1));
         if(e.currentTarget.classList.contains('active')){
            removeValue(params, 'with_genres', genres[e.target.innerText]); 
            console.log('remove genre');
        }else if(!e.target.classList.contains('active')){
            url.searchParams.append('with_genres', genres[e.target.innerText]);
            console.log('add genre');
        } 
        
        fetchURL(url);
    }
}
body {
  margin: 0;
  padding: 0;
  --primary-color: #39445a;
  --secondary-color: rgb(34, 24, 24);
  background-color: var(--primary-color);
}

.app {
  display: flex;
  flex-direction: column;
  width: 100%;
  min-height: 100vh;
  background-color: var(--secondary-color);
}

.app h1 {
  font-family: "Montserrat", sans-serif;
  text-transform: uppercase;
  text-align: center;
  color: #39445a;
  font-size: 2em;
  font-weight: 900;
}

.movie_container {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
}

.movie {
  cursor: pointer;
  display: flex;
  flex-direction: column;
  width: 200px;
  padding: 5px;
  margin: 5px 15px;
  background-color: #282c34;
  border-radius: 10px;
  font-family: "Montserrat", sans-serif;
}

.movie .movie_title {
  font-family: "Montserrat", sans-serif;
  text-transform: uppercase;
  color: #fff;
  font-size: 1em;
  font-weight: 900;
  text-align: center;
}

.genres {
  display: flex;
  justify-content: center;
  flex-wrap: wrap;
  margin: 10px;
}

.genres .genre {
  color: rgba(0, 0, 0, 0.87);
  display: flex;
  align-items: center;
  text-transform: capitalize;
  cursor: pointer;
  background-color: #fff;
  line-height: 3px;
  border-radius: 10px;
  padding: 5px 15px;
  font-size: 0.850rem;
  margin: 2px;
  font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
}

.genres .genre.active {
  color: #fff;
  background-color: #3f51b5;
}
<div class="app">
  <h1>discover movies</h1>
  <div class="genres">
    <div class="genre">action</div>
    <div class="genre">adventure</div>
    <div class="genre">animation</div>
    <div class="genre">comedy</div>
    <div class="genre">crime</div>
    <div class="genre">documentary</div>
    <div class="genre">drama</div>
    <div class="genre">family</div>
    <div class="genre">fantasy</div>
    <div class="genre">history</div>
    <div class="genre">horror</div>
    <div class="genre">music</div>
    <div class="genre">mystery</div>
    <div class="genre">romance</div>
    <div class="genre">science fiction</div>
    <div class="genre">TV movie</div>
    <div class="genre">thriller</div>
    <div class="genre">war</div>
    <div class="genre">western</div>
  </div>
  <div class="movie_container" id="movie_container">
    <div class="movie">
      <img src="img/dark_knight.jpg">
      <span class="movie_title">the dark knight</span>
    </div>
  </div>


from How can I delete just one parameter with urlsearchparams.delete()?

No comments:

Post a Comment