Recently diving into Vue, I've been working on creating a form that triggers an API call whenever an input is changed. The main goal is to dynamically populate and set other inputs based on the user's selection of a vehicle.
For example, when a user selects a make, the model and year fields are populated with appropriate values fetched from the API using WebSocket. Additionally, these fields can also be automatically filled out by entering the VIN (vehicle identification number), and any changes in one field may affect the others.
This has resulted in a feedback loop where modifying one input leads to changes in another input, triggering additional API calls and further updates.
I'm looking for ways to ensure that data is only set once after a user manually changes a field.
Below is my current code for selecting a vehicle:
<template>
<div id="vehicleSelection">
<h1 class="title">{{ title }}</h1>
<b-field label="Make">
<b-select placeholder="Select a make" v-model="make" @input="setMake(make)" id="makeSelect">
<option
v-for="make in make_list"
:value="make"
:key="make">
{{ make }}
</option>
</b-select>
</b-field>
<b-field label="Model">
<b-select placeholder="Select a model" v-model="model" @input="setModel(model)" id="modelSelect">
<option
v-for="model in model_list"
:value="model"
:key="model">
{{ model }}
</option>
</b-select>
</b-field>
<b-field label="Year">
<b-select placeholder="Select a model year" v-model="year" @input="setYear(year)" id="yearSelect">
<option
v-for="year in year_list"
:value="year"
:key="year">
{{ year }}
</option>
</b-select>
</b-field>
</div>
</template>
<script>
import CommandClient from '../communication/command/CommandClient';
import MessageHandler from '../communication/handler/MessageHandler';
export default {
name: 'VehicleSelection',
methods: {
setMake(make) {
CommandClient.send(this.$socket, CommandClient.prepare('set_vehicle_make', ['make', make]));
},
setModel(model) {
CommandClient.send(this.$socket, CommandClient.prepare('set_vehicle_model', ['model', model]));
},
setYear(year) {
CommandClient.send(this.$socket, CommandClient.prepare('set_vehicle_year', ['year', year]));
},
},
created() {
this.$options.sockets.onmessage = (message) => {
MessageHandler.handle(this, message);
};
},
data() {
return {
title: 'Vehicle Selection',
make_list: [],
make: null,
model_list: [],
model: null,
year_list: [],
year: null,
};
},
};
</script>
Although there is some repetition in the code which will need refactoring later on, my immediate focus is on getting it to function correctly.
As for context, the MessageHandler module included here takes a Vue component as input and sets its data if the key matches in the API response:
const _ = require('lodash');
export default {
/**
* @param {Object} context
* @param {MessageEvent} message
* @return {void}
*/
handle(context, message) {
const messagePayload = JSON.parse(message.data);
Object.entries(messagePayload).forEach((data) => {
if (_.has(context.$data, data[0])) {
context.$set(context, data[0], data[1]);
}
});
},
};