简体   繁体   中英

Javascript: Finding values in array/object to determine Form display

Let me set up the situation:

I have a form. This form has several fields which are dependent upon a single drop-down, lets call it Art Kind . Based on the value of this Art Kind, several other fields are to be hidden/shown. Multiple values within this Art Kind dropdown can trigger the same set of fields being shown. For example.

User selects "Awesome", or "Cool", from the Art Kind dropdown:
     - URL and Name fields are shown
 User selects "Rainbow", or "Double Rainbow", from the Art Kind dropdown: - URL and Name fields are hidden - Color and Size fields are shown 

I think you get the idea.

I'm trying to come up with a better solution than something like this:

if (selected == "Awesome" || selected == "Cool")
{
    url.show();
    name.show();
}

Because there are a ton of fields, and a ton of different options that need be shown/hidden depending on selection. I've dabbled in an array, but I'm lost on how to get what I need accomplished.

I was thinking about storing the options in a multidimensional array, or an object, something like:

var values = [
     ['Awesome', 'Cool'], ['url', 'name']
]

But I'm not sure how to implement such a thing.

Any ideas? I'm open to answers that involve jQuery for simplification, but I'd rather keep other libraries out of it.

It'd be better to use an object, with the <select> values being the keys. Now as to the values, it's hard to say without knowing more details.

If there are only a few different overall page setups — that is, combinations of things shown and things hidden — then it might be easiest to encapsulate those in a few functions, and have the map go from selected value to function:

function rainbowMode() {
  // show color and size, hide url and name ...
}

function awesomeMode() {
  // show url and name, hide color and size ...
}

var actionMap = {
  'Rainbow': rainbowMode,
  'DoubleRainbow': rainbowMode,
  'Awesome': awesomeMode,
  // ...
};

An entirely different approach would be to tie the selection to the addition/removal of one or more CSS classes to the form container, coupled with CSS rules to hide/show portions of the form. The only catch with this is that you can't make form fields be disabled via CSS alone, so if you need the form posts to not include inappropriate fields that won't really help.

I've been thinking of writing a jQuery plugin to service this very need :-) If I do I'll update the answer in a couple of months. (I've already got the code; I just need to yank it out of its current context.)

A similar idea to @Pointy's, somewhat different execution.

function hideAllFormElements()
{
    // snip...
}

function showElements(ids)
{
    for (var i=0; i<ids.length; i++)
    {
        document.getElementById(ids[i]).style.display = 'none';
    }
}

var mapping = {
    Awesome: ['url', 'name'],
    Cool: ['url', 'name'],
    Rainbow: ['color', 'size'],
    'Double Rainbow': ['color', 'size']
};

// later...
hideAllFormElements();
showElements(mapping[selected]);

Edit

Because jQuery is the bee's knees, instead of separate hide/show functions this will suffice, given just var mapping = {...} as above:

$('#mySelect').change(function ()
{
    var selected = $(this).val();

    $('#myForm :input').hide();
    $.each(mapping[selected], function ()
    {
        $('#' + this).show();
    });

    // or if you want to get really fancy,
    $($.map(mapping[selected], function ()
    {
        return '#' + this;
    }).get().join(', ')).show();
});

I've done exactly this by using the 'rel' tag, which is mostly unused in HTML. Note that my example uses jQuery, but can be easily adapted to any other JS framework, or straight Javascript.

<select id="artkind">
    <option value="cool">Cool</option>
    <option value="awesome">Awesome</option>
    <option value="rainbow">Rainbow</option>
    <option value="2xrainbow">Double Rainbow</option>
</select>

<input name="url" rel="cool awesome">
<input name="name" rel="cool awesome">
<input name="color" rel="rainbow 2xrainbow">
<input name="size" rel="rainbow 2xrainbow">

<script>
    $('#artkind').change(function() {
        $('input').hide(); // To hide everything
        $('[rel*="'+this.value+'"]').show(); // To show only desired fields
    })
</script>

Note, I haven't actually tested this exact code, so I can't guarantee it works as-is. But I have used this exact method before for the exact thing you're talking about.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM