Home > Back-end >  How to operate with only one array in composition API Vue 3
How to operate with only one array in composition API Vue 3

Time:12-06

I'm new in vue 3, and I need your help. I created vue app that uses rest API to fetch the data. Also I added the features as filter and search to my application. But when I use filter or search function, it creates another computed arrays. First array is data, another is filteredData and third is filterByDate. Please, can you tell me, how to operate only with one araay in an app. Thanks in advance! There is a code of my component.

<template>
  <Loading v-if="isLoading" />
  <AsteroidLayout
    v-else
    :data="data"
    :fetchData="fetchData"
    :plusDay="plusDay"
    :changeDay="changeDay"
  >
    <div >
      <input
        type="text"
        
        placeholder="Search an asteroid by name"
        v-model="searchQuery"
      />
    </div>
    <button @click="sorted = !sorted">Filter by close approach date</button>
    <div v-if="sorted" v-for="asteroid in filterByDate" :key="asteroid.name">
      <Asteroids :asteroid="asteroid" />
    </div>
    <div v-for="asteroid in filteredData" :key="asteroid.id">
      <Asteroids :asteroid="asteroid" />
    </div>
  </AsteroidLayout>
</template>

<script>
import { onMounted, ref } from "vue";
import { addDays } from "date-fns";
import { computed } from "vue";
import Loading from "../components/Loading.vue";
import AsteroidLayout from "../components/AsteroidLayout.vue";
import Asteroids from "../components/Asteroids.vue";
export default {
  components: {
    Loading,
    AsteroidLayout,
    Asteroids,
  },
  setup() {
    const API_KEY = "Kzb0E64htPxZGEM33UC62hrug7mfHAzEzIH8Qyu1";
    const data = ref([]);
    const isLoading = ref(false);
    const sorted = ref(false);
    const plusDay = ref(0);
    const searchQuery = ref("");
    onMounted(() => {
      fetchData(data.value);
    });
    const fetchData = (type) => {
      isLoading.value = true;
      data.value = type;
      fetch(
        `https://api.nasa.gov/neo/rest/v1/feed?end_date=${getDate()}&&api_key=${API_KEY}`
      )
        .then((res) => res.json())
        .then((res) => {
          let fetchedData = res.near_earth_objects[getDate()];
          data.value = fetchedData;
          isLoading.value = false;
        })
        .catch(() =>
          alert(
            "Sorry, we can't load the asteroids data. Please try again later or check your internet connection"
          )
        );
    };

    const getDate = () => {
      return `${addDays(new Date(), plusDay.value).toISOString().substring(0, 10)}`;
    };

    const changeDay = (day) => {
      plusDay.value  = day;
      fetchData(data.value);
    };
    const filteredData = computed(() => {
      return data.value.filter((asteroid) => {
        return asteroid.name.toLowerCase().indexOf(searchQuery.value.toLowerCase()) != -1;
      });
    });
    const filterByDate = computed(() => {
      return data.value.sort((a, b) => {
        return (
          Date.parse(new Date(a.close_approach_data[0].close_approach_date_full)) -
          Date.parse(new Date(b.close_approach_data[0].close_approach_date_full))
        );
      });
    });
    return {
      data,
      isLoading,
      fetchData,
      plusDay,
      changeDay,
      filteredData,
      searchQuery,
      filterByDate,
      sorted,
    };
  },
};
</script>

<style scoped>
.inputWrapper {
  text-align: right;
}

.search {
  border: none;
  height: 30px;
  width: 200px;
  outline: none;
  border: 3px solid var(--secondary);
  border-radius: 35px;
  color: black;
  font-size: 14px;
  font-weight: 200;
  text-align: center;
}
</style>

And there is a screenshot of the vue devtools enter image description here

                                                                                                               

CodePudding user response:

You need just 1 computed prop for your searchQuery

You can try this instead

const filteredData = computed(() => {
      let modifiedData = data.value;
      
      if(sorted.value){
        modifiedData = modifiedData.sort((a, b) => {
          return (
             Date.parse(new Date(a.close_approach_data[0].close_approach_date_full)) -
             Date.parse(new Date(b.close_approach_data[0].close_approach_date_full))
          );
        });
      }

      if(searchQuery.value !== ''){
        modifiedData =  modifiedData.filter((asteroid) => {
          return asteroid.name.toLowerCase().indexOf(searchQuery.value.toLowerCase()) != -1;
        });

      }
     
     return modifiedData;
});

In HTML

<div v-for="asteroid in filteredData" :key="asteroid.name">
    <Asteroids :asteroid="asteroid" />
</div>

This way you have sorted as well as filtered data according to searchQuery and all modifications are on original data which you received from api.

  • Related