1

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

3 Answers 3

4

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).

Sign up to request clarification or add additional context in comments.

3 Comments

Using $(this).eq() doesn't make sense as there is only one selected element.
you are correct, my implementation was incorrect because i needed to cache the object. changes made, jsFiddle provided as well.
Thanks so much for the help! I got a modified version of your third solution working perfectly. I'm not sure why it wasn't working out of the box, but it's perfect now. I'll add my working script below my question. Thanks again!
2

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

Comments

2

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.

2 Comments

Nice work, i can add many number of dropdowns and the id need not be mentioned in the script, Thank you.
And is there any chance you can add some more script where i can add a new text box and append that text in the middle of two dropdown values. like in the below fiddle. jsfiddle.net/raja777m/6z97d523/#base Thanks in advance.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.