Steve Dimock
Steve Dimock

Reputation: 151

Populating an input from two drop-downs with Jquery

So I've got an input field that I'm trying to populate using two separate drop-down menus. I've got it working with a single drop-down currently, but I'm unable to do two. Here's an example of what I'm trying to accomplish:

<select type="text" id="make">
    <option value="">- select one -</option>
    <option value="chevy">Chevy</option>
</select>
<select type="text" id="model">
    <option value="">- select one -</option>
    <option value="silverado">Silverado</option>
</select>
<input type="text" id="input" value="" />

So the value of the text input should be 'Chevy Silverado' if both fields are selected. Here's the script that I've got so far:

$(function(){
    $('select#make').bind('change', function(){
        $('input#input').val($(this).val());
    });
});

Which works great for one drop down, but obviously does nothing for the other. Any ideas? I've tried a few solutions that I'd found with absolutely no success. Thanks for looking!

Big thanks to those of you who answered my question! With your guidance I was able to get the below code working for me perfectly. Note that I DID add an additional class to my select boxes

    $(function(){
    var $makemodel = $('.makemodel');
    $('.makemodel').on('change',function(){
        $('#input').val($makemodel.eq(0).val()+' '+$makemodel.eq(1).val());
    });
});

Upvotes: 1

Views: 2026

Answers (3)

David Thomas
David Thomas

Reputation: 253318

I'd suggest amending the HTML somewhat, to group the select elements within a single parent, and binding, using on(), the change event to that element:

<form action="#" method="post">
    <fieldset>
        <select type="text" id="make">
            <option value="">- select one -</option>
            <option value="chevy">Chevy</option>
        </select>
        <select type="text" id="model">
            <option value="">- select one -</option>
            <option value="silverado">Silverado</option>
        </select>
        <input type="text" id="input" value="" />
    </fieldset>
</form>

With the jQuery:

$('fieldset').on('change', function(){
    var self = $(this);
    $('#input').val(function(){
        return self.find('select').map(function(){ return this.value; }).get().join(' ');
    });
});

JS Fiddle demo.

Modifying further, to use a class to identify the summary element (the text-input into which the value will be inserted) reduces the reliance on known elements, and allows for more general-purpose code:

$('fieldset').on('change', function(){
    var self = $(this);
    self.find('.summary').val(function(){
        return self.find('select').map(function(){ return this.value; }).get().join(' ');
    });
});

JS Fiddle demo.

And a non-jQuery, plain-JavaScript approach to the same solution (albeit only works in those browsers that support document.querySelector()/document.querySelectorAll() and addEventListener()):

function summarise(container, what, sumClass) {
    var els = container.querySelectorAll(what),
        sumTo = container.querySelector(sumClass),
        vals = [];
    for (var i = 0, len = els.length; i < len; i++) {
        vals.push(els[i].value);
    }
    sumTo.value = vals.join(' ').trim();
}

var fieldsets = document.querySelectorAll('fieldset');

for (var i = 0, len = fieldsets.length; i < len; i++) {
    fieldsets[i].addEventListener('change', function(){
        summarise(this, 'select', '.summary');
    }, false);
}

JS Fiddle demo.

Upvotes: 2

PlantTheIdea
PlantTheIdea

Reputation: 16359

No problem! Please forgive the length of this answer, it offers multiple options depending on whether you place greater importance on code readability vs efficiency. It will only make marginal differences in speed but hopefully it shall inspire you to think of speed in your overall code!

Easy solution:

$('#make,#model').on('change',function(){
    $('#input').val($('#make').val()+' '+$('#model').val());
});

More efficient:

Give your selects a class:

<select type="text" id="make" class="MakeModel">
    <option value="">- select one -</option>
    <option value="chevy">Chevy</option>
</select>
<select type="text" id="model" class="MakeModel">
    <option value="">- select one -</option>
    <option value="silverado">Silverado</option>
</select>
<input type="text" id="input" value="" />

And then select on the class:

$('.MakeModel').on('change',function(){
    $('#input').val($('#make').val()+' '+$('#model').val());
});

Giving it a class just makes it slightly easier for the parser to query only one selector rather than two.

Most efficient:

Use the appropriate .eq() values and caching instead of querying the ID selectors again:

var $makemodel = $('.MakeModel');

$makemodel.on('change',function(){
    $('#input').val($makemodel.eq(0).val()+' '+$makemodel.eq(1).val());
});

This means the select items do not need to be requeried since all the objects of .MakeModel are contained within the function under the cached $makemodel and you can just specify the object order number to reference a specific one.

jsFiddle to show what I mean here

Additional notes:

Notice the use of .on rather than .bind, which is the more correct syntax for modern jQuery applications.

Also, using tagnames before ID or class will actually make your selectors less efficient, as the parser needs to verify the ID/class is associated with the tag, rather than just grabbing the ID (which should be unique anyway) or class name (which should be appropriately isolated in its naming).

Upvotes: 4

Valery Viktorovsky
Valery Viktorovsky

Reputation: 6726

Simple solution:

$(function() {
    $('#make, #model').on('change', function() {
        var makeCurr = $('#make').find(":selected");
        var madelCurr = $('#model').find(":selected");
        var make = (makeCurr.val() != '') ? makeCurr.text() : '';
        var model = (madelCurr.val() != '') ? madelCurr.text() : '';

        $('input#input').val(make + ' ' + model);
    });
});

View Example

Upvotes: 2

Related Questions