I have certain form inputs that are only displayed depending on other input’s value. I am trying to control when inputs fadeOut() and fadeIn() with, I think, a promise() but it seems the call-stack still runs everything synchronously – maybe I am not configuring the promise correctly?
Here is some pseudo code. The catch here is one of my inputs, input3 needs to be removed, then re-added to correct some JQuery validation and JQuery automcomplete rules, so I am trying to create the function to do that, every time that function is called to fadeIn().
function display_input1() {
return new Promise(function (resolve) {
resolve(hide_input3())
var new_element = `...`
$(new_element)
.hide()
.insertAfter(
$("#input0")
)
$("new_element").fadeIn("fast")
})
}
function hide_input1() {
$("#input1")
.fadeOut("fast", function () {
$("#input1").remove()
})
}
function display_input2(data) {
var new_element = `...`
$(new_element)
.hide()
.insertAfter(
$("#input0")
)
$("new_element").fadeIn("fast")
}
function hide_input2() {
$("#input2")
.fadeOut("fast", function () {
$("#input2").remove()
})
}
function display_input3(search_type) {
return new Promise(function (resolve) {
resolve(hide_input1(), hide_input3())
if (search_type == "some_varible") {
var new_element = `...`
} else if (search_type == "some_variable") {
var new_element - `...`
}
$(new_element)
.hide()
.insertAfter(
$("#input2")
)
$("new_element").fadeIn("fast")
})
}
function hide_input3() {
if ($("#input3").length) {
$("#input3")
.fadeOut("fast", function () {
$("#input3").remove()
})
}
}
$(document).on("change", "#input0", function (e) {
var option = $(this).find("option:selected")
var data = AJAX response
if (data["some_attr"]) {
display_input2(data)
hide_input1()
} else {
hide_input2()
if (data["some_attr"]) {
if (!$("#input1").length) {
display_input1()
}
} else {
hide_input1()
}
}
})
$(document).on("change", "input2", function (e) {
var option = this
if (option.value === "input1") {
display_input1()
} else if (["input2", "input3"].includes(option.value)) {
if (option.value === "input2") {
var search_type = "some_varible"
} else {
var search_type = "some_varibale"
}
display_input3(search_type)
}
})
$(document).on("click", "button.cancel", function (e) {
hide_input1()
hide_input2()
hide_input3()
$(form).validate().resetForm()
})
UPDATE
Based on comments, I’ve reflected my code block for better understanding. I’ve consolidated functions in hopes to make the code more malleable.
function display_form_input(input_type, search_type = null, data = null) {
if (input_type == "input_var1") {
var new_element = `...`
$(new_element)
.hide()
.insertAfter(
$("#input1")
)
$("#input1").fadeIn("fast")
} else if (input_type == "input_var2") {
var new_element = `...`
$(new_element)
.hide()
.insertAfter(
$("#input0")
)
$("#input2").fadeIn("fast")
} else if (input_type == "input_var3") {
if (search_type == "some_var1") {
var new_element = `...`
} else if (search_type == "some_var2") {
var new_element = `...`
}
$(new_element)
.hide()
.insertAfter(
$("#input3")
)
$("#input3").fadeIn("fast")
}
}
function hide_form_input(input_type) {
return new Promise(function (resolve) {
if (input_type == "input_var1") {
$("#input1")
.fadeOut("fast", function () {
$("#input1").remove()
resolve()
})
} else if (input_type == "input_var2") {
$("#input2")
.fadeOut("fast", function () {
$("#input2").remove()
resolve()
})
} else if (input_type == "input_var3") {
$("#input3")
.fadeOut("fast", function () {
$("#input3").remove()
resolve()
})
}
})
}
$(document).on("change", "#input0", function (e) {
var option = $(this).find("option:selected")
$.ajax({
...
success: function (data) {
if (data["key1"]) {
hide_form_input("input_var1")
display_form_input(
"input_var2",
null,
(data = data["key1"]),
)
} else {
hide_form_input("input_var2")
if (data["key2"] && !$("#input1").length) {
display_form_input("input_var1")
}
}
},
})
})
$(document).on("change", "#input2", function (e) {
var option = this
if (option.value === "value1") {
var search_form = hide_form_input("input_var3")
search_form
.promise()
.done(display_form_input("input_var1"))
} else if (["value2", "value3"].includes(option.value)) {
if (option.value === "value2") {
var search_type = "value22"
} else {
var search_type = "value33"
}
hide_form_input("input_var1")
var search_form = hide_form_input("input_var3")
search_form
.promise()
.done(display_form_input("input_var3", search_type))
}
})
$(document).on("click", "button.cancel", function (e) {
var items = ["input_var1", "input_var2", "input_var3"]
items.forEach(function (item) {
hide_form_input(item)
})
$(form).validate().resetForm()
})
Advertisement
Answer
Thanks to @Bergi and @ControlAltDel for walking me through understanding .promise(). I now have a working example I was trying to achieve! Thank you guys so much for your patience.
Here is my working example in pseudo code. I made some improvements too on a function based @Bergi comments (always strive for DRY code)
function display_form_input(input_type, search_type = null, data = null) {
/*
create_form_input: Display the form input for a given input_type.
Args:
input_type (str): The type of input to create.
Optional Args:
search_type (str): The type of results expected from this search.
Returns:
None
*/
if (input_type == "input_var1") {
var new_element = `...`
$(new_element)
.hide()
.insertAfter(
$("#input0").closest("div.row").children(),
)
$("#input1").parents(":eq(1)").fadeIn("fast")
} else if (input_type == "input_var2") {
var new_element = `...`
$(new_element)
.hide()
.insertAfter($("#input0").closest("div.row"))
$("#input2").parents(":eq(2)").fadeIn("fast")
} else if (input_type == "input_var3") {
if (search_type == "some_var1") {
var new_element = `...`
} else if (search_type == "some_var2") {
var new_element = `...`
}
$(new_element)
.hide()
.insertAfter($("#input2").closest("div.row").children())
$("#input3").parents(":eq(1)").fadeIn("fast")
}
}
function hide_form_input(input_type) {
/*
hide_form_input: Hide the form input for a given input_type.
Args:
input_type (str): The type of input to hide.
Returns:
JQuery Promise.
*/
if (input_type == "input_var1") {
var form_element = $("#input1").parents(":eq(1)")
} else if (input_type == "input_var2") {
var form_element = $("#input2").parents(":eq(2)")
} else if (input_type == "input_var3") {
var form_element = $("#input3").parents(":eq(1)")
}
return form_element
.fadeOut("fast")
.promise()
.then(function () {
form_element.remove()
})
}
$(document).on("change", "#input0", function (e) {
/*
Event Handler: Trigger what form field to display when a the input0
changes.
*/
var option = $(this).find("option:selected")
$.ajax({
...
success: function (data) {
if (data["key1"]) {
hide_form_input("input_var1").then(function () {
if (!$("#input2").length) {
display_form_input(
"input_var2",
null,
data["key1"],
)
}
})
} else {
hide_form_input("input_var2")
if (data["key2"] && !$("#input1").length) {
display_form_input("input_var1")
} else if (!data["key2"]) {
hide_form_input("input_var2")
}
}
},
})
})
$(document).on("change", "#input2", function (e) {
/*
Event Handler: Trigger what form field to display when a the input2
changes.
*/
var option = this
if (option.value === "value1") {
hide_form_input("input_var3").then(function () {
display_form_input("input_var1")
})
} else if (["value2", "value3"].includes(option.value)) {
if (option.value === "value2") {
var search_type = "some_var1"
} else {
var search_type = "some_var2"
}
hide_form_input("input_var1")
hide_form_input("input_var3").then(function () {
display_form_input("input_var3", search_type)
})
}
})
$(document).on("click", "button.cancel", function (e) {
/*
Event Handler: Make form back to default state.
*/
var button = this
var form = $($(button).closest("form"))
var items = ["input_var1", "input_var2", "input_var3"]
items.forEach(function (item) {
hide_form_input(item)
})
$(form).validate().resetForm()
})