Mantis
Mantis

Reputation: 1387

binding select via ajax in knockout

I have a form that posts to a remote API. The form works fine but I need to populate the options in the select boxes with an Ajax call.

This is what I have so far but clueless on the next step.

form.html

<form data-bind="submit: mySubmit" role="form">
    <select data-bind="
        options: operative,
        optionsValue: 'id',
        optionsText: function(i) {
            return i.FirstName + ' ' + i.LastName
        },
        optionsCaption: 'Choose...'
    "></select>
    <select data-bind="
        options: claim,
        optionsValue: 'id',
        optionsText: function(i) {
            return i.id
        },
        optionsCaption: 'Choose...'
    "></select>

    <textarea data-bind="value: body" cols="23" rows="5"></textarea>
    <input data-bind="value: entryDate" type="text">
    <button type="submit">Go</button>
</form>

javascript

var viewModel = {
    operative: ko.observable(),
    claim: ko.observable(),
    body: ko.observable(),
    entryDate: ko.observable(),
    operative: [{}],
    claims: [{}],
    mySubmit : function(formElement) {
        var formData = {
            'operative' : viewModel.firstname() ,
            'claim'  : viewModel.lastname(),
            'body' : viewModel.firstname() ,
            'entryDate'  : viewModel.lastname()
        };
        console.log(formData)

        $.ajax({
            url: '/api/entry/',
            type: "POST",
            data: JSON.stringify(formData),
            datatype: "json",
            processData:false,
            contentType: "application/json; charset=utf-8",
            success: function (result){
                alert("success");
            }
        });
    }
};

ko.applyBindings(viewModel);

Upvotes: 0

Views: 2833

Answers (2)

Tomalak
Tomalak

Reputation: 338128

I need to populate the options in the select boxes with an Ajax call.

Well, make them observable (i.e. ko.observableArray()), issue your Ajax requests and fill them when they return.

(I've made a few other subtle changes to your code, read carefully.)

var viewModel = {
    operatives: ko.observableArray(),
    claims: ko.observableArray(),
    body: ko.observable(),
    entryDate: ko.observable(),
    selectedOperative: ko.observable(),
    selectedClaim: ko.observable(),
    submit: function () {
        $.post('/api/entry/', {
            operative: this.selectedOperative(),
            claim: this.selectedClaim(),
            body: this.body(),
            entryDate: this.entryDate()
        }, 'json').done(function (result){
            console.log('submit success', result);
        });
    }
};

$.get('/api/operatives/').done(viewModel.operatives);
$.get('/api/claims/').done(viewModel.claims);

ko.applyBindings(viewModel);

and

<form data-bind="submit: submit" role="form">
    <select data-bind="
        value: selectedOperative,
        options: operatives,
        optionsValue: 'id',
        optionsText: function(i) {
            return i.FirstName + ' ' + i.LastName
        },
        optionsCaption: 'Choose...'
    "></select>
    <select data-bind="
        value: selectedClaim,
        options: claims,
        optionsValue: 'id',
        optionsText: id
        optionsCaption: 'Choose...'
    "></select>

    <textarea data-bind="value: body" cols="23" rows="5"></textarea>
    <input data-bind="value: entryDate" type="text">
    <button type="submit">Go</button>
</form>

Note that this:

$.get('/api/operatives/').done(viewModel.operatives);

is equivalent to:

$.get('/api/operatives/').done(function (result) {
    viewModel.operatives(result);
});

Of course it depends on your API íf you can take this little shortcut.

Upvotes: 2

Starscream1984
Starscream1984

Reputation: 3062

You would need to declare an observable array and then call your ajax endpoint immediately (this snippet assumes your ajax result doesn't need any processing to be used as the options):

myOptions: ko.observableArray(),

$.ajax({
        url: '/api/optionsUrl/',
        type: "GET",
        datatype: "json",
        processData:false,
        contentType: "application/json; charset=utf-8",
        success: function (result){
            myOptions(result);
        }
    });

Then you can set those options in your html:

<select data-bind="
    options: myOptions,
    optionsValue: 'id',
    optionsText: function(i) {
        return i.id
    },
    optionsCaption: 'Choose...'
"></select>

Upvotes: 2

Related Questions