Search code examples
backbone.jsbackbone-stickit

Backbone stickit selectOptions from ajax


I am trying to populate a select using below.

 View: Backbone.View.extend({
                    initialize: function () {
                        this.setElement($('#templatePlaceholder'));
                    },
                    bindings: {

                        'select#List': {
                            observe: 'ddList',
                            selectOptions: {
                                collection: Q.when(getSelects.execute()).then(function (data) {
                                    console.dir(data);
                                    return data;
                                })

                            }
                        }
                    },

console returns an array object:

 [ { value: 1, label: "a" },   { value: 2, label: "b" } ]

But I get nothing.

If I define collection as:

collection: function () { return [{ value: 1, label: "a" },{ value: 2, label: "b" }];}

then all works fine.


Solution

  • There is potentially a couple of problems with this: that asynchronous code is executing immediately as View is being assigned which may not be desired; and collection is getting assigned to the result of executing that promise, not whatever is being returned by return data.

    Some solutions:

    1) You could bootstrap your select options on page load. This is a popular pattern in single page or Backbone apps. Basically, you have the backend put together json data-structures of common data and then render it to the page as a javascript variable. So the server side template (jsp, erb, php) would look something like this:

    <!DOCTYPE html>
    ...
        <script type="text/javascript">
           window.bootstrap = { users: <%= userjson %>, ddlist: <%= ddlistjson %> };
        </script>
    ...
    

    This method is recommended for performance and convenience.

    2) If you have the option to run getSelects.execute() synchronously - for example if it is a jQuery ajax request, run it with the async:false option - then you could execute it in a couple of places in the view. During initialize will fetch the data when the view is actually constructed. Or you could assign your collection binding with a function that runs the getSelects routine, which blocks and then returns the data:

    collection: function() {
        var collection = [];
        // Assumes that getSelects.execute() will block and run synchronously.
        Q.when(getSelects.execute()).then(function (data) {
           collection = data;
        });
        return collection;
    }
    

    This method is not recommended as it could leave your UI in a funky state as it blocks other javascript from running, and could potentially get hung up.