Подтвердить что ты не робот

Коллекция Fetch Backbone с параметрами поиска

Я хотел бы реализовать страницу поиска с помощью Backbone.js. Параметры поиска берутся из простой формы, и сервер знает, как анализировать параметры запроса и возвращает массив json результатов. Моя модель выглядит примерно так:

App.Models.SearchResult = Backbone.Model.extend({
    urlRoot: '/search'
});

App.Collections.SearchResults = Backbone.Collection.extend({
    model: App.Models.SearchResult
});

var results = new App.Collections.SearchResults();

Мне бы хотелось, чтобы каждый раз, когда я выполнял results.fetch(), содержимое формы поиска также сериализовалось с запросом GET. Есть ли простой способ добавить это, или я делаю это неправильно, и, вероятно, нужно вручную кодировать запрос и создавать коллекцию из возвращаемых результатов:

$.getJSON('/search', { /* search params */ }, function(resp){
    // resp is a list of JSON data [ { id: .., name: .. }, { id: .., name: .. }, .... ]
    var results = new App.Collections.SearchResults(resp);

   // update views, etc.
});

Мысли?

4b9b3361

Ответ 1

Backbone.js fetch с параметрами отвечает на большинство ваших вопросов, но я также добавил некоторые из них.

Добавьте параметр data к вызову fetch, например:

var search_params = {
  'key1': 'value1',
  'key2': 'value2',
  'key3': 'value3',
  ...
  'keyN': 'valueN',
};

App.Collections.SearchResults.fetch({data: $.param(search_params)});

Теперь ваш URL-адрес вызова добавил параметры, которые вы можете проанализировать на стороне сервера.

Ответ 2

Внимание: код упрощен и не протестирован

Я думаю, вы должны разделить функциональность:

Модель поиска

Это правильный ресурс на вашей стороне сервера. Разрешено только действие CREATE.

var Search = Backbone.Model.extend({
  url: "/search",

  initialize: function(){
    this.results = new Results( this.get( "results" ) );
    this.trigger( "search:ready", this );
  }
});

Коллекция результатов

Он отвечает за сбор списка моделей результатов

var Results = Backbone.Collection.extend({
  model: Result
});

Форма поиска

Вы видите, что этот вид выполняет интеллектуальное задание, слушая form.submit, создавая новый объект Search и отправляя его на сервер created. Эта миссия created не означает, что поиск должен храниться в базе данных, это нормальное поведение creation, но это не всегда должно быть таким образом. В нашем случае CREATE Поиск означает поиск в БД, который ищет конкретные регистры.

var SearchView = Backbone.View.extend({
  events: {
    "submit form" : "createSearch"
  },

  createSearch: function(){
    // You can use things like this
    // http://stackoverflow.com/questions/1184624/convert-form-data-to-js-object-with-jquery
    // to authomat this process
    var search = new Search({
      field_1: this.$el.find( "input.field_1" ).val(),
      field_2: this.$el.find( "input.field_2" ).val(),
    });

    // You can listen to the "search:ready" event
    search.on( "search:ready", this.renderResults, this )

    // this is when a POST request is sent to the server
    // to the URL `/search` with all the search information packaged
    search.save(); 
  },

  renderResults: function( search ){
    // use search.results to render the results on your own way
  }
});

Я думаю, что такое решение очень чистое, элегантное, интуитивное и очень расширяемое.

Ответ 3

Нашел очень простое решение - переопределить функцию url() в коллекции:

App.Collections.SearchResults = Backbone.Collection.extend({

  urlRoot: '/search',

  url: function() {
    // send the url along with the serialized query params
    return this.urlRoot + "?" + $("#search-form").formSerialize();
  }
});

Надеюсь, это не ужасает любого, у кого есть немного больше навыков магистральной /Javascript, чем я.

Ответ 4

Кажется, что текущая версия Backbone (или, может быть, jQuery) автоматически строит значение data, поэтому нет необходимости называть $.param больше.

Следующие строки дают одинаковый результат:

collection.fetch({data: {filter:'abc', page:1}});
collection.fetch({data: $.param({filter:'abc', page:1})});

Запрос будет filter=abc&page=1.

EDIT: Это должен был комментарий, а не ответ.