简体   繁体   中英

Knockout JS Cascading State / City Dropdown (with JSON)

I have two fields, state and city. When the user selects their state I'm sending a call to the server which is returning:

[{"id":"4488","rc_abbr":"BILLINGS"},{"id":"4489","rc_abbr":"MISSOULA"},{"id":"4490","rc_abbr":"GREATFALLS"},{"id":"4491","rc_abbr":"HELENA"},{"id":"4492","rc_abbr":"BOZEMAN"},{"id":"4493","rc_abbr":"BUTTE"},{"id":"4494","rc_abbr":"HAMILTON"},{"id":"4495","rc_abbr":"BELGRADE"},{"id":"4496","rc_abbr":"LIVINGSTON"},{"id":"4497","rc_abbr":"LAUREL"},{"id":"4498","rc_abbr":"MILES CITY"},{"id":"4499","rc_abbr":"STEVENSVL"},{"id":"4500","rc_abbr":"LEWISTOWN"},{"id":"4501","rc_abbr":"ANACONDA"},{"id":"4502","rc_abbr":"DILLON"},{"id":"4503","rc_abbr":"HARDIN"},{"id":"4504","rc_abbr":"GLENDIVE"},{"id":"4505","rc_abbr":"DEER LODGE"},{"id":"4506","rc_abbr":"SIDNEY"},{"id":"4507","rc_abbr":"CUT BANK"},{"id":"4508","rc_abbr":"MANHATTAN"},{"id":"4509","rc_abbr":"RED LODGE"},{"id":"4510","rc_abbr":"FRENCHTOWN"},{"id":"4511","rc_abbr":"THREEFORKS"},{"id":"4512","rc_abbr":"COLUMBUS"},{"id":"4513","rc_abbr":"CONRAD"},{"id":"4514","rc_abbr":"SHELBY"},{"id":"4515","rc_abbr":"COLSTRIP"},{"id":"4516","rc_abbr":"WYELLOWSTN"},{"id":"4517","rc_abbr":"FORSYTH"},{"id":"4518","rc_abbr":"GALATNGTWY"},{"id":"4519","rc_abbr":"JOLIET"},{"id":"4520","rc_abbr":"GARDINER"},{"id":"4521","rc_abbr":"CLYDE PARK"},{"id":"4522","rc_abbr":"FROMBERG"},{"id":"4523","rc_abbr":"FAIRVIEW"},{"id":"4524","rc_abbr":"BRIDGER"},{"id":"4525","rc_abbr":"WIBAUX"},{"id":"4526","rc_abbr":"TERRY"},{"id":"4527","rc_abbr":"WILSALL"},{"id":"4528","rc_abbr":"WOLF CREEK"},{"id":"4529","rc_abbr":"COOKE CITY"},{"id":"4530","rc_abbr":"SILVERTIP"},{"id":"4531","rc_abbr":"NO PARKMAN"}]

In knockout I need to update the city field with this data. My problem is something to do with the way I'm getting the ajax data success response and putting it in, I'm not sure on the proper syntax.

Here is the fiddle: http://jsfiddle.net/VJbVs/

HTML

<select data-bind="value: selectedState">
<option value="AL">Alabama</option>
<option value="AK">Alaska</option>
<option value="AZ">Arizona</option>
<option value="AR">Arkansas</option>
<option value="CA">California</option>
<option value="CO">Colorado</option>
<option value="CT">Connecticut</option>
<option value="DE">Delaware</option>
<option value="DC">District of Columbia</option>
<option value="FL">Florida</option>
<option value="GA">Georgia</option>
<option value="HI">Hawaii</option>
<option value="ID">Idaho</option>
<option value="IL">Illinois</option>
<option value="IN">Indiana</option>
<option value="IA">Iowa</option>
<option value="KS">Kansas</option>
<option value="KY">Kentucky</option>
<option value="LA">Louisiana</option>
<option value="ME">Maine</option>
<option value="MD">Maryland</option>
<option value="MA">Massachusetts</option>
<option value="MI">Michigan</option>
<option value="MN">Minnesota</option>
<option value="MS">Mississippi</option>
<option value="MO">Missouri</option>
<option value="MT">Montana</option>
<option value="NE">Nebraska</option>
<option value="NV">Nevada</option>
<option value="NH">New Hampshire</option>
<option value="NJ">New Jersey</option>
<option value="NM">New Mexico</option>
<option value="NY">New York</option>
<option value="NC">North Carolina</option>
<option value="ND">North Dakota</option>
<option value="OH">Ohio</option>
<option value="OK">Oklahoma</option>
<option value="OR">Oregon</option>
<option value="PA">Pennsylvania</option>
<option value="RI">Rhode Island</option>
<option value="SC">South Carolina</option>
<option value="SD">South Dakota</option>
<option value="TN">Tennessee</option>
<option value="TX">Texas</option>
<option value="UT">Utah</option>
<option value="VT">Vermont</option>
<option value="VA">Virginia</option>
<option value="WA">Washington</option>
<option value="WV">West Virginia</option>
<option value="WI">Wisconsin</option>
<option value="WY">Wyoming</option>
</select>
<select data-bind="options: cities, optionsText: 'Name', optionsValue: 'ID', value: selectedCity"></select>

Script

(function () {

    var ViewModel = function () {

        this.selectedState = ko.observable();
        this.selectedState.states = [];

        this.selectedCity = ko.observable();

        this.selectedState.subscribe(function () {
            this.selectedCity(undefined);
        }, this);

        var getById = function (items, id) {
            return ko.utils.arrayFirst(items, function (item) {
                $.ajax({
                    url: 'activate/get/coverage',
                    type: 'POST',
                    beforeSend: function(){},
                    data: ko.toJSON({state: item.ID}),
                    contentType: 'application/json',
                    complete: function(data){}, 
                    success: function (result) {this.selectedState.states = result;}
                });
                return item.ID == id;
            });
        };

        this.cities = ko.computed(function () {
            var state = getById(this.selectedState.states, this.selectedState());
            return state ? ko.utils.arrayMap(state.States, function (item) {
                return {
                    id: item.ID,
                    rc_abbr: item.Name
                };
            }) : [];
        }, this);

    };

    var model = new ViewModel();
    ko.applyBindings(model, document.getElementById('didScreen'));

})();

I'm posting this as an answer, we spent a lot of time in chat talking (don't know if others can open that link).

The HTML:

<div data-bind="foreach: items">
    <select data-bind="options: $parent.states, optionsText: 'name', value: state"></select>
    <select data-bind="options: cities, optionsText: 'name', value: city"></select>
    <button data-bind="click: $parent.remove">Remove</button>
</div>
<button data-bind="click: newItem">Add Item</button>

The JS:

var Item = function() {
    var self = this;
    self.state = ko.observable();
    self.city = ko.observable();
    self.cities = ko.observableArray([]);
    self.state.subscribe(function(state) {
        self.city("");
        self.cities.removeAll();
        $.ajax({
            url: '/echo/json/',
            type: 'POST',
            data: {
                json: ko.toJSON([
                    { id: 1, name: "Billings"},
                    { id: 2, name: "Sweego"},
                    { id: 3, name: "NorthFall"}
                ]),
                delay: 2
            },
            success: function(response) {
                self.cities(response);
            }
        });
    });
};

var ViewModel = function(states) {
    var self = this;
    self.states = states;
    self.items = ko.observableArray([new Item()]);
    self.newItem = function() {
        self.items.push(new Item());
    };
    self.remove = function(item) {
        self.items.remove(item);
    };
};

Here is the final fiddle

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