web-dev-qa-db-fra.com

Récupérer la collection Backbone avec les paramètres de recherche

Je voudrais implémenter une page de recherche en utilisant Backbone.js. Les paramètres de recherche sont extraits d'un simple formulaire et le serveur sait analyser les paramètres de requête et renvoyer un tableau json des résultats. Mon modèle ressemble plus ou moins à ceci:

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

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

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

J'aimerais que chaque fois que j'exécute results.fetch(), le contenu du formulaire de recherche sera également sérialisé avec la demande GET. Existe-t-il un moyen simple d'ajouter cela, ou est-ce que je le fais de la mauvaise façon et devrait probablement coder manuellement la demande et créer la collection à partir des résultats renvoyés:

$.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.
});

Pensées?

21
sa125

Backbone.js récupère avec les paramètres répond à la plupart de vos questions, mais j'en mets aussi ici.

Ajoutez le paramètre data à votre appel fetch, par exemple:

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

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

Maintenant, votre URL d'appel a ajouté des paramètres que vous pouvez analyser côté serveur.

84
jakee

Attention: code simplifié et non testé

Je pense que vous devriez diviser la fonctionnalité:

Le modèle de recherche

C'est un bon ressource côté serveur. La seule action autorisée est CREATE.

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

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

La collection de résultats

Il est juste chargé de collecter la liste des modèles de résultats

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

Le formulaire de recherche

Vous voyez que cette vue fait le travail intelligent, en écoutant le form.submit, créant un nouvel objet Search et l'envoyant au serveur pour être created. Cette mission created ne signifie pas que la recherche doit être stockée dans la base de données, c'est le comportement normal de creation, mais cela n'a pas toujours besoin d'être ainsi. Dans notre cas create a Search signifie rechercher dans la base de données à la recherche des registres concrets.

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

Je pense que ce type de solution est très propre, élégant, intuitif et très extensible.

13
fguillen

Il semble que la version actuelle de Backbone (ou peut-être jQuery) stringifie automatiquement la valeur data, il n'est donc pas nécessaire d'appeler $.param plus.

Les lignes suivantes produisent le même résultat:

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

La chaîne de requête sera filter=abc&page=1.

EDIT: Cela aurait dû être un commentaire plutôt qu'une réponse.

6
alekop

Trouvé une solution très simple - remplacez la fonction url() dans la collection:

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

Espérons que cela n'horrifie personne qui possède un peu plus de compétences Backbone/Javascript que moi.

6
sa125