Reactivity of a long to calculate prop in Vue.js

37 views Asked by At

I have a Vue component that receives two props: values (an object containing various fields including name) and apiResponse (initially an empty object).
The component includes a name field that should display apiResponse.name when apiResponse is updated with data from an API call. If apiResponse.name is not available, the field should display values.name instead.
I would like to make the name field in the component dynamically update to show apiResponse.name once the API call completes and apiResponse is populated with data.

I am then working with these 2 props.
I tried to put apiResponse as a watch but the logs do not display in my console when apiResponse gets calculated. I know it does get calculated because I have a <div> that displays its value directly, and that correctly updates when apiResponse changes.

I tried to make accountValues a computed value that will be this.values.name or this.apiResponse.name based on wether the first one is empty or not.

But it does not work and I would greatly appreciate some help :)

Here is my Vue component that I simplified the most I could (I hope I did not forget unrelevant bits of code):

<template>
  <div v-if="apiResponse">
    <h3>Company Name: {{ apiResponse.company.name }}</h3>
  </div>
  <div v-else>
    <h3>Company Name: waiting for api response </h3>
  </div>
  <TextField
    :value="accountValues"
    :warning="displayNameWarning"
    v-model="name"
    name="account-name"
    label="Name"
    rules="required"
    class="col-span-6 sm:col-span-2">
    <template #warningMessage>
      {{ nameWarning.message }}
    </template>
  </TextField>
</template>

<script>
import { defineComponent } from "vue";
import TextField from "../TextField";
import TagsField from "../TagsField";
import TextareaField from "../TextareaField";
import SelectField from "../SelectField";
import { debounce, find, isEmpty, size } from "lodash";
import postApi from "../../../api";

export default defineComponent({
  components: {
    TextField,
    TextareaField,
    SelectField,
    TagsField,
  },

  props: {
    values: {
      type: Array,
      default: null,
    },
    apiResponse: {
      type: Object,
      default: ({}),
    },
  },

  data() {
    return {
      name: '',
      nameWarning: {},
      mlValues: {},
    }
  },

  mounted() {
    if (this.values) {
      if (this.values.record_type === this.accountTypes[1]) {
        this.showPortfolioCompanyId = false;
      } else if (this.values.record_type === this.accountTypes[2]) {
        this.showPortfolioCompanyId = true;
      }

      this.showOccupation = this.isLimitedPartner(this.values.record_type);
      this.showIndustry = !this.isLimitedPartner(this.values.record_type);
    }

  },

  watch: {
    name: {
      handler(newValue, oldValue) {
        this.checkName(newValue);
      }
    },
    apiResponse: {
      handler(newValue, oldValue) {
        console.log('apiResponse changed');
        console.log(newValue);
        console.log(oldValue);
        
        this.mlValues.name = newValue.company.name;
      }
    }
  },

  computed: {
    users() {
      return this.$page.props.users;
    },

    isFromUSA() {
      return find(
        this.$page.props.permissions,
        { name: 'pre-fill USA fields' }
      ) !== undefined;
    },

    displayNameWarning() {
      return !isEmpty(this.nameWarning);
    },

    accountValues() {
      
      const ret = this.values ? this.values : this.mlValues;
      console.log('accountValues', ret);
      return ret;
    }

  },

  methods: {
    handleAccountType: function(newValue) {
      this.showIndustry = !this.isLimitedPartner(newValue);
      this.showOccupation = this.isLimitedPartner(newValue);
      this.showPortfolioCompanyId = newValue === this.accountTypes[2];
    },

    checkName: debounce(async function(string) {

      this.nameWarning = {};

      if(string === "" || string.length <= 4) {
        return;
      }

      const response = await postApi("/nova-vendor/forms/check/account/name", { 'name': string });
      const result = await response.json();

      const nbResult = size(result);

      if(nbResult) {
        this.nameWarning = {
          message: nbResult + ' account(s) with a similar name',
          data: result
        }
      }
    }, 500),

  },

});
</script>
0

There are 0 answers