Recent searches


No recent searches

How do I set the form dropdown value through javascript?

Answered


Posted Jan 16, 2024

Purpose

  • Show an alert telling the user they need to be logged in when selecting certain form types in the request type drop-down
  • Redirect them to the login page if they click accept in the alert dialog
  • Stay on the same page and change nothing if they decline

Progress

  • Show alert to the user when they select one of the specific form types while being anonymous/not logged in
  • Don't redirect to the request form url when the alert shows
  • Redirect to the login page when they accept the alert

Problems

  • When the cancel the alert, they are still on the same page, but the drop-down value is showing the wrong value
    • If they had no form selected, the drop-down looks wrong and behaves weirdly
    • If they had another form selected, the drop-down looks wrong, and while everything else looks the same, if the user tries to send in the form, it fails. It fails, because the form thinks it's the new form but the user only filled in the fields shown on the screen, which is of the original form.
  • Can't figure out how to change the drop-down value back to the original value through code. None of the standard way of doing this through JavaScript is working.

Example Code

This being a stripped down version of my code, most of this works fine, everything except the line 31: "dropdown.value = previousForm;"
Which I also have issues with just doing in the console; any tries to modify the selected drop-down value through code, will not do anything. Trying to see the value of the select element in the console correctly shows what I'm setting through code, but what the user sees is completely different/wrong.

Example Images

Image 1

After selecting "I want to report a bug or crash" while not having any form selected, and then declining the alert dialog that shows up, I end up in this state

See console that everything looks as it should, but the drop-down is behaving weirdly

Image 2

Moreover, if I then open the drop-down, the "I want to report a bug or crash" is highlighted in bold, and selecting it will not do anything. However, selecting "-" which is what I was on, and should currently be on, refreshes the page, most likely meaning the drop-down back-end believes I am on the "I want to report a bug or crash" form. (Which clearly I am not as no fields are showing, and I haven't been redirected)

Conclusion

I'm having an awful time trying to do any kind of manipulation of drop-downs in themes, and I'm at my wits end.
This is on the latest version of the official Copenhagen theme version 3.1.6, with very minimal modifications, only adding custom JavaScript alongside the existing JavaScript.

Any and all help is greatly appreciated!


0

3

3 comments

image avatar

Brandon Tidd

Zendesk LuminaryUser Group LeaderThe Humblident Award - 2021Community Moderator

Hey Isak Viste

Thanks for posting such a thoroughly documented answer!

Manipulating dropdowns in JavaScript can be a bit tricky due to the way the DOM updates the state of <select> elements. Here are a few steps and tips that might help resolve the issue:

  1. Ensure Binding is Correct: Confirm that your event listeners are bound correctly and that no other JavaScript code is interfering with the dropdown's behavior.

  2. Use selectedIndex: Instead of setting dropdown.value, try using dropdown.selectedIndex. This property reflects the index of the first or last selected <option> element and is a 0-based number.

  3. Prevent Default Behavior: To ensure that selecting the dropdown doesn't trigger any other behavior that might be conflicting with your JavaScript, use event.preventDefault() in your event listener before any other logic.

  4. Force a Redraw: Sometimes, forcing a redraw of the element can help the DOM reflect the changes made by JavaScript. This can be done by hiding and showing the dropdown, or by triggering a reflow/repaint.

Here's a revised version of your event listener that uses selectedIndex:

 

dropdown.addEventListener("change", function (event) {
    if (event.target.value !== '12345') {
        return;
    }
    
    event.preventDefault(); // Prevent any default behavior
    event.stopPropagation(); // Stop the event from propagating

    Swal.fire({ /* ... */ }).then((result) => {
        if (result.isConfirmed) {
            window.location.href = "/hc/signin";
        } else {
            // Find the index of the previous value
            const previousIndex = Array.from(dropdown.options).findIndex(option => option.value === previousForm);

            if (previousIndex >= 0) {
                // Set the selectedIndex to the previous index
                dropdown.selectedIndex = previousIndex;
            } else {
                // If the previousForm was not found, clear the selection or set it to a default
                dropdown.selectedIndex = -1; // This will deselect all options
            }

            // Force a redraw of the dropdown if needed
            dropdown.style.display = 'none';
            dropdown.offsetHeight; // Trigger a reflow
            dropdown.style.display = '';

        }
    });
}, true);

If this doesn't solve the problem, consider the following:

  • Check for other event listeners: There might be other event listeners attached to the dropdown that interfere with your code.
  • Check for CSS/Styling Issues: Sometimes, CSS can affect the visual state of a dropdown. Make sure there is no CSS that changes the visual state of options based on their selected state.

1


Thank you Brandon, I appreciate you taking the time to write such a thorough detailed response! 
Unfortunately, none of the tricks seems to work in my case.

The issue, as far as I can tell, is that Zendesk uses some trick to hide the select field behind an <a> element with a lot of js to make it work and look like a select field. Hence when I change the select field through code, it is not the same way as if a user interacted with it.

If I show the select field using a display = "", I can see that select field is right under the other field and looks correct:
But I can't figure out how to update the <a> nesty-input field that is above the select field.

I have tried to remove the <a> nesty-input field and just show the select field, but that breaks Zendesks submit form code that relies on that field for it's logic. This also explains why I had some weird cases I mentioned previously, as its role is not only visually, but also influences what form is being submitted (instead of the select field which I thought was the decider).

I've tried redrawing both the hidden select field, and the nesty-input a element but neither works. I cannot just change the inner html of the nesty-input a element either, as though it will then look correct, programmatically it is not. It keeps the selected form/index in code somewhere hidden.
This is all from trying and debugging in the console, and the little I could understand from the obfuscated code in the "hc_enduser-xxxx.js" file

Any thoughts on the matter?

0


image avatar

Brandon Tidd

Zendesk LuminaryUser Group LeaderThe Humblident Award - 2021Community Moderator

Hi Isak Viste

When you programmatically change the <select> element's value, the visual components (like the <a> element you mentioned) do not automatically update because they have event listeners that synchronize their state based on user interactions, not programmatic changes.

To manipulate such components, you often need to trigger the events or call the methods provided by the library itself to update the visual component and synchronize it with the <select> element. If Zendesk uses a library for this, you would need to find out which one it is and use its API to update the component.

Here is a general approach that might work if your guide uses a common library like "Chosen":

// Simulate a mouse click on the dropdown's visual representation
var nestyInput = document.querySelector('.nesty-input');
var event = new MouseEvent('mousedown', {
    'view': window,
    'bubbles': true,
    'cancelable': true
});
nestyInput.dispatchEvent(event);

// After a brief delay, simulate selecting the option
setTimeout(function() {
    // You would need to figure out how to select the option based on Zendesk's implementation
    // This might involve simulating clicks on specific child elements of the dropdown
}, 100);

Due to the complexity of this issue and the potential for breaking changes, ensure that any solution is thoroughly tested across different browsers and devices to prevent disrupting the user experience.

1


Please sign in to leave a comment.

Didn't find what you're looking for?

New post