Question

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.

Was it helpful?

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.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top