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>