Two Vue components conflicting each other while loading data

69 Views Asked by At

I have a "ProjectsSearchBar" component for searching and selecting projects that are making calls to API to fetch projects. I am trying to place two same components side by side. Unfortunately, only one of them is loading data, the other kind of resets? In short, it loads endlessly. If i delete second component, it works normally. It's like they're overwriting each other. In addition, when I log the query result of both components to the console, it turns out that only one pops up. I looked at various threads, but the only answer I found was that for both components you have to give :key. I did, it didn't work. I also gave a key to an element in the component. It didn't work either. If you have any idea, I'd be grateful.

That's how it looks:

<ProjectsSearchBar
  key="component1"
  v-model="mergeProject"
  :multiple="false"
  :clearable="true"
  label="Wybierz projekt główny"
/>
<ProjectsSearchBar
  key="component2"
  v-model="absorbedProjects"
  :multiple="true"
  :clearable="true"
  label="Wybierz projekty wchłaniane"
/>

ProjectsSearchBar code:

<template>
  <v-autocomplete
    :value="value"
    :items="projectsItems"
    :loading="isLoadingData"
    :search-input.sync="searchProject"
    outlined
    :clearable="clearable"
    :chips="multiple"
    :small-chips="multiple"
    deletable-chips
    item-text="name"
    :item-value="getValueWrapper"
    :label="label"
    placeholder="Wpisz by wyszkać"
    :multiple="multiple"
    @input="handleInput"
    @change="$emit('change', value)"
  >
    <template #item="data">
      <template v-if="typeof data.item !== 'object'">
        <v-list-item-content v-text="data.item" />
      </template>
      <template v-else>
        <v-list-item-content>
          <v-list-item-title v-html="data.item.name" />
          <v-list-item-subtitle v-if="data.item.client">
            {{ data.item.client.name }}
          </v-list-item-subtitle>
          <v-list-item-subtitle v-if="data.item.job_types">
            {{ itemHourlyRate(data.item.job_types) }}
          </v-list-item-subtitle>
        </v-list-item-content>
      </template>
    </template>
  </v-autocomplete>
</template>

<script>
export default {
  name: 'ProjectsSearchBar',
  props: {
    value: {
      // some props
    },
  },
  data: () => ({
    selected: [],
    searchProject: '',
    isLoadingData: true,
    projects: [],
  }),
  computed: {
    user: get('auth/user'),
    currentPartyId: get('global/currentPartyId'),
    projectsItems() {
      let currentItems = [];
      if (this.value !== null) {
        currentItems = Array.isArray(this.value) ? this.value : [this.value];
      } else {
        currentItems = [];
      }
      const current = currentItems.map((el) => el.id);
      const projects = this.projects.filter((el) => !current.includes(el.id));
      return [...currentItems, ...projects];
    },
    itemHourlyRate() {
      return (jobTypes) => {
        if (jobTypes && this.selectedJobType) {
          const selectedType = jobTypes.find((type) => type.id === this.selectedJobType.id);

          if (selectedType) {
            return `Stawka dla wybranego typu pracy: ${selectedType.pivot.hourly_rate} zł/h`;
          }
        }
        return '';
      };
    },
  },
  watch: {
    searchProject() {
      this.searchDebounce();
    },
    clientIds() {
      this.searchDebounce();
    },
  },
  methods: {
    searchDebounce: debounce(function () {
      this.fetchProjects();
    }, 300),
    handleInput(e) {
      this.$emit('input', e);
      this.searchProject = '';
    },
    getValueWrapper(el) {
      return el;
    },
    async fetchProjects() {
      this.isLoadingData = true;
      try {
        const result = await this.$API.projects.getProjects(
          this.currentPartyId,
          {
            page: 1,
            limit: 20,
            project_name: this.searchProject,
            client_id: this.clientIds,
            status: this.statuses,
          },
        );
        this.projects = result.data.data;

        this.$emit('projects-loaded', this.projects);
      } catch (e) {
        // eslint-disable-next-line no-console
        console.error(e);
      } finally {
        this.isLoadingData = false;
      }
    },
  },
};
</script>

Thanks for any advice. If you need anything else, let me know. I am using Vue 2.0

0

There are 0 best solutions below