0

I've got a collection that does a url request,

class Movieseat.Collections.Moviesearch extends Backbone.Collection

  url: ->
    "http://api.themoviedb.org/3/search/movie?api_key=a8f7039633f2065942cd8a28d7cadad4&query=#{@query}"

  setQuery: (q) ->
    @query = q
    return

I've got a view that renders a template, in the template is a input field. When text is typed in the input field the Collection gets updated with the value and when there's a keyup action in the input field the collection gets fetched.

class Movieseat.Views.Moviesearch extends Backbone.View

  template: JST['movieseats/moviesearch']
  el: '#moviesearch'

  initialize: (opts) ->
    {@collection} = opts
    @render()
    return

  render: ->
    $(@el).html(@template())
    return

  events:
    "keyup input": "doSearch"

  doSearch: (e) ->
    inputtext = @$("form#autocomplete-remote input").val()
    console.log inputtext
    @collection.setQuery $(e.currentTarget).val()
    @collection.fetch()

And now I'm trying to render each result in a li element, but I don't know how to do that. What would be the next step for me?

4
  • Can you create code snippet? Commented Oct 22, 2014 at 19:55
  • jsfiddle.net/dxpowx27/92 Commented Oct 22, 2014 at 20:26
  • Backbone version used in fiddle is 0.5.3, last stable version is 1.1.2. Could we use last one? Commented Oct 22, 2014 at 21:29
  • jsfiddle.net/dxpowx27/119 Updated it with the latest Backbone and Underscore. Commented Oct 23, 2014 at 7:32

2 Answers 2

1

After a little play with your source code I came up with the following solution:

MoviesCollection = Backbone.Collection.extend({
    url: function () {
        return "http://api.themoviedb.org/3/search/movie?api_key=a8f7039633f2065942cd8a28d7cadad4&query=" + this.query;
    },
    setQuery: function (q) {
        this.query = q;
    },
    parse: function (response) {
        return response.results;
    }
});

ResultsView = Backbone.View.extend({
    initialize: function (opts) {
        this.collection = opts.collection ;
        this.collection.on('sync',  this.render, this);
    },
    el: '#result-list', 
    template: _.template($("#results_template").html()),
    render: function () {
        var that = this;
        this.$el.html(this.template({movies:  this.collection.toJSON()}));
    }
});

MoviesView = Backbone.View.extend({
    initialize: function (opts) {
        this.collection = opts.collection;
        this.render();
    },
    pressDelay: 500,
    el: "#search_container",
    template: _.template($("#search_template").html()),
    render: function(){
      this.$el.html(this.template());
        var resultsView = new ResultsView({collection: this.collection})  ;
        resultsView.render();
    },
    events: {
        'keyup input': 'doSearch'
    },
    doSearch: function (event) {
        if (this.timeoutId) {
          clearTimeout(this.timeoutId);
        }
        this.timeoutId = setTimeout($.proxy(this.fetchValues, this), this.pressDelay);
        
    },
    fetchValues:  function() {
        // add check here for empty values, no need to fetch collection if input is empty
        var inputtext =  this.$el.find('input').val();
        console.log (inputtext);
        var that = this;
        this.collection.setQuery(inputtext);
        this.collection.fetch();
    }
    
});

myCollection = new MoviesCollection();

var search_view = new MoviesView({
    collection: myCollection
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.7.0/underscore-min.js"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/backbone.js/1.1.2/backbone-min.js"></script>

<script type="text/template" id="results_template">
    <ul id="search_container-results">
        <% _.each(movies, function(movie) { %> 
        <li class="original_title"><%= movie.title %></li> 
        <% }); %>
     </ul>
</script>
    
 <div id="search_container"></div>

<script type="text/template" id="search_template">
    <form id="autocomplete-remote">
        <input type="text" id="search_input" value="Star" />
        <input type="button" id="search_button" value="Search" />
    </form>
    <div id="result-list">
        
    </div>
</script>

I have added timeout between input events, to increase queries frequency. You can configure it using pressDelay property of MoviesView.

Sign up to request clarification or add additional context in comments.

Comments

0

Take a look at listenTo and the list of built in events.

I think you probably want to listen to the collection's events and call a render method when something changes.

For example, you could add this to your initialize to re-render when the collection is fetched:

this.listenTo(this.collection, 'sync', this.render);

Or you could just render a single item when it's added to the collection:

this.listenTo(this.collection, 'add', this.renderItem);

1 Comment

it looks like your a step ahead of me. I should indeed watch for changes on the collection to update my DOM. But if you take it one step back you can see that I don't have a way yet to render out the JSON to a nice li element.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.