Now that we’ve coded up a solution, how can we simplify this without committing serious sins?
We have a select source field, an input target field, and a data reference.
Move the trigger code to a separate function
That code to trigger a change event when the page loads is easier to understand when it’s in a separate function.
function triggerEvent(eventName, el) {
const event = new MouseEvent(eventName, {
view: window,
bubbles: true,
cancelable: true
});
el.dispatchEvent(event);
}
...
triggerEvent("change", companyInfo);
And we can now focus more easily on the rest.
Is it possible to give a function those important things, and have it connect everything together?
Ways that we can simplify
Let’s try it. One possible way is to use a data object:
updateField({
source: "#companyForm [name=companyInfo]",
valueCallback: getCompanyRate,
target: "#companyForm [name=companyRate]"
});
However, a simpler way is to have the function take three arguments. It is possible to just send those selectors to the function instead, but functions tend to be more difficult to use when selectors are used instead of actual element references.
function updateField(source, target, callback) {
}
const form = document.querySelector("#companyForm");
const source = form.elements.companyInfo;
const target = form.elements.companyRate;
updateField(source, target, getCompanyRate);
That looks to be about the simplest we can make it.
The source field is where we get the value from. That value is fed to the callback function which gets the company rate, and the target is where that company rate is placed. It is standard for the callback to be the last argument of the function.
Move code into updateField function
We can now move the remaining code into the updateField function, renaming things like companyInfo to their appropriate counterparts, like source.
function updateField(source, target, callback) {
// function infoChangeHandler(evt) {
function infoChangeHandler() {
// const selectInfo = evt.target;
// const infoValue = selectInfo.value;
// const companyRate = getCompanyRate(infoValue);
// form.elements["companyRate"].value = companyRate;
target.value = callback(source.value);
}
// const companyInfo = form.elements.companyInfo;
// companyInfo.addEventListener("change", infoChangeHandler);
source.addEventListener("change", infoChangeHandler);
triggerEvent("change", source);
}
const form = document.querySelector("#companyForm");
const source = form.elements.companyInfo;
const target = form.elements.companyRate;
updateField(source, target, getCompanyRate);
Inline getCompanyRate
We can inline the getCompanyRate function, making it easier to understand how we use the info value to get the company rate:
updateField(source, target, function getCompanyRate(infoValue) {
const dataRow = company_data.find(
(data) => data.company_id === infoValue
);
return dataRow.company_rate;
});
The updated code
With the comments of previous code removed, that give us the following code in total:
function triggerEvent(eventName, el) {
const event = new MouseEvent(eventName, {
view: window,
bubbles: true,
cancelable: true
});
el.dispatchEvent(event);
}
function updateField(source, target, callback) {
function infoChangeHandler(evt) {
target.value = callback(source.value);
}
source.addEventListener("change", infoChangeHandler);
triggerEvent("change", source);
}
const form = document.querySelector("#companyForm");
const source = form.elements.companyInfo;
const target = form.elements.companyRate;
updateField(source, target, function getCompanyRate(infoValue) {
const dataRow = company_data.find(
(data) => data.company_id === infoValue
);
return dataRow.company_rate;
});
The updated code is found at https://jsfiddle.net/pmw57/zxp9ytso/