Chained Selects Plugin for jQuery and Zepto

Blog Projects
JavaScript jQuery Zepto
Chained is simple chained selects plugin. It works with both jQuery and Zepto. Use class based version if you do not want to make external queries. It uses HTML class names of select options to decide content. To create selects from AJAX queries use remote version instead. This version makes an external AJAX query and uses the returned JSON to build child selects.

See standalone demo page for quick working example.

Class Based Usage

Child selects are chained to parent select. Child select options must have class names which match option values of parent select. When user selects something in parent select the options in child select are updated. Options which have matching classname with parents currently selected option will stay visible. Others are hidden.

NOTE! Class names are case sensitive. This means Audi and audi will not match.

First you must include jQuery and Chained in your code:

<script src="//ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
<script src="jquery.chained.min.js"></script>

Then lets assume you have the following HTML code:

<select id="mark" name="mark">
  <option value="">--</option>
  <option value="bmw">BMW</option>
  <option value="audi">Audi</option>
</select>
<select id="series" name="series">
  <option value="">--</option>
  <option value="series-3" class="bmw">3 series</option>
  <option value="series-5" class="bmw">5 series</option>
  <option value="series-6" class="bmw">6 series</option>
  <option value="a3" class="audi">A3</option>
  <option value="a4" class="audi">A4</option>
  <option value="a5" class="audi">A5</option>
</select>

You can now chain the #series to #mark. There are two different ways to do it. Choose yourself if you prefer more english like or shorter version. I prefer the shorter version.

$("#series").chained("#mark"); /* or $("#series").chainedTo("#mark"); */
Try here to see how it works.

Many Selects

Let’s add a third select. Because we all love coupes don’t we? Notice how there is a coupe for BMW series 3 and 6 and also Audi A5. Sportback is only for Audi A3 and A5.

<select id="model" name="model">
  <option value="">--</option>
  <option value="coupe" class="series-3 series-6 a5">Coupe</option>
  <option value="cabrio" class="series-3 series-6 a3 a5">Cabrio</option>
  <option value="sedan" class="series-3 series-5 a3 a4">Sedan</option>
  <option value="sportback" class="a3 a5">Sportback</option>
</select>

Now lets chain #model to #series.

$("#series").chained("#mark");
$("#model").chained("#series");
Try here to see how it works.

Chaining to Multiple Parents

One child can also have two parents. Options on child which is chained to multiple parents depend on one or both of the parents selected values. To make child select depend on values of both parents use classname like first\second.

Here is HTML for fourth select. Note how diesel engine is available only for BMW 3 and 5 series Sedans. This is achieved by using classnames series-3\sedan and series-5\sedan.

<select id="engine" name="engine">
  <option value="">--</option>
  <option value="25-petrol" class="series-3 a3 a4">2.5 petrol</option>
  <option value="30-petrol" class="series-3 series-5 series-6 a3 a4 a5">3.0 petrol</option>
  <option value="30-diesel" class="series-3\sedan series-5\sedan a5">3.0 diesel</option>
</select>
$("#series").chained("#mark");
$("#model").chained("#series");
$("#engine").chained("#series, #model");
Try here to see how it works.

Using Remote Version

Using the remote version is similar to what has been explained above. First include jQuery or Zepto and remote version of Chained:

<script src="//ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
<script src="jquery.chained.remote.min.js"></script>

In HTML you only need to provide option tags for the first select. Contents of other selects will be built from JSON returned by AJAX request. AJAX request is done when value of parent select changes.

<select id="mark" name="mark">
  <option value="">--</option>
  <option value="bmw">BMW</option>
  <option value="audi">Audi</option>
</select>
<select id="series" name="series">
  <option value="">--</option>
</select>
<select id="model" name="model">
  <option value="">--</option>
</select>
<select id="engine" name="engine">
  <option value="">--</option>
</select>

In code you must use remoteChained() method. Second parameter is URL where the AJAX request is sent.

$("#series").remoteChained({
    parents : "#mark",
    url : "/api/series.json"
});

$("#model").remoteChained({
    parents : "#series",
    url : "/api/model.json"
});

$("#engine").remoteChained({
    parents : "#series, #model",
    url : "/api/engine.json"
});
Try here to see how it works.

When change event is triggered on parent select a GET request is sent to the given URL. This request includes the name and value of the parent in the query string. For example when users selects BMW in the first select the following request is made:

GET http://example.com/api/series.json?mark=bmw

Chained expects JSON response which contains value – text pairs for each option.

{
  "" : "--",
  "series-1" : "1 series",
  "series-3" : "3 series",
  "series-5" : "5 series",
  "series-6" : "6 series",
  "series-7" : "7 series",
  "selected" : "series-6"
}

If you need to be able to sort entries on server side use array of arrays…

[
  [ "", "--" ],
  [ "series-1", "1 series" ],
  [ "series-3", "3 series" ],
  [ "series-5", "5 series" ],
  [ "series-6", "6 series" ],
  [ "series-7", "7 series" ],
  [ "selected", "series-6" ]
]

… or array of objects.

[
  { "" : "--" },
  { "series-1" : "1 series" },
  { "series-3" : "3 series" },
  { "series-5" : "5 series" },
  { "series-6" : "6 series" },
  { "series-7" : "7 series" },
  { "selected" : "series-6" }
]

Bootstrapped selects

There are cases when you know values of the selects on page load. For example when linking directly to a saved order or a specific car model. When you know the values you can bootstrap the remote selects by giving the values in the options. This also avoids making the initial AJAX requests. If you have HTML code like below.

<select id="mark" name="mark">
  <option value="">--</option>
  <option value="bmw" selected>BMW</option>
  <option value="audi">Audi</option>n
</select>
<select id="series" name="series">
  <option value="--">--</option>
</select>

To have BMW Series 3 selected by default you can bootstrap the select values.

$("#series").remoteChained({
    parents : "#mark",
    url : "/api/series.json",
    bootstrap : {
        "" : "--",
        "series-3" : "3 series",
        "series-5" : "5 series",
        "series-6" : "6 series",
        "series-7" : "7 series",
        "selected" : "series-3"
    }
});
Values are already selected.

Send additional values

Sometimes you want to send more values than only the parent selects. Lets say you have select for transmission. Content of transmission select changes when user chooses new engine. However in your database possible different transmissions also depend on what series the car is. You have four different selects.

<select id="mark" name="mark">
    <option value="">--</option>
    <option value="bmw" selected>BMW</option>
    <option value="audi">Audi</option>
</select>

<select id="series" name="series">
    <option value="--">--</option>
</select>

<select id="engine" name="engine">
    <option value="--">--</option>
</select>

<select id="transmission" name="transmission">
  <option value="--">--</option>
</select>

Then you could use the following code to send values of both #series and #engine to server.

$("#transmission").remoteChained({
    parents : "#engine",
    url : "/api/transmissions.json",
    depends : "#series"
});
PRO TIP! Parent select values are always sent. You do not have include then in depends setting.

Show loading text

If JSON queries are slow you might want to show loading text. Set value of loading to a string. It will be shown while AJAX request is being processed.

$("#engine").remoteChained({
    parents : "#engine, #model",
    url : "/api/series.json",
    loading : "Loading..."
});
Try here to see how it works.

Install

Download latest minified or remote version minified. You can also install with bower.

>bower install chained



When asking a question include an URL to example page where the problem occurs. Even better is to make a Fiddle which demonstrates the problem. If you have longer code examples please use pastie.org.
CATEGORIES
Built using the awesome Flat UI Pro framework by Designmodo.

Mika Tuupola is a Member of the Leanpub Affiliate Program.

© 2014 Mika Tuupola.