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() })