0

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

2 Answers 2

2

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.

1
  • For more complex situations, look into using the mapping plugin. It offers a lot more flexibility in terms of viewmodel population.
    – Tomalak
    Commented Sep 8, 2015 at 9:17
2

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>

Not the answer you're looking for? Browse other questions tagged or ask your own question.