Après notre introduction à Backbone.js, nous allons voir dans cette partie comment aller plus loin en insérant des données.
Le code de cette application Backbone est disponible sur github.
Pour commencer nous allons enrichir notre layout d’un nouveau template javascript.
<script type="text/template" id="new_category">
<input id="category_name" name="category[name]" type="text" placeholder="Type a category…" />
<input type="button" id="save-new-category" value="Enregistrer" />
</script>
Nous allons simplement mettre à disposition un champ et un bouton.
Côté contrôleur, rien qu’une action create classique. Nous allons simplement préparer nos messages d’erreur pour un affichage côté client.
def create
@category = Category.new params[:category]
if @category.save
respond_with(@category)
else
render :status => 500, :json => @category.errors.full_messages.join(', ')
end
end
Il nous reste à préparer notre vue Backbone.js.
class NewCategoryView extends Backbone.View
tagName: 'form'
template: _.template($('#new_category').html())
events:
'keypress #category_name': 'saveNewCategoryIfSubmit'
'click #save-new-category': 'saveNewCategory'
'focusout #category_name': 'emptyMessages'
initialize: ->
_.bindAll(@, 'render')
@collection.bind 'reset', @render
render: ->
$(@el).html @template()
@
saveNewCategoryIfSubmit: (event) ->
if event.keyCode is 13
event.preventDefault()
saveNewCategory()
saveNewCategory: ->
attributes = { category: { name: $("#category_name").val() } }
@collection.create(attributes, { error: @showErrors })
emptyMessages: ->
$("#messages").empty()
showErrors: (model, errors) ->
@emptyMessages()
$("#messages").html(errors.responseText)
@app.NewCategoryView = NewCategoryView
Le template sera enrobé dans un formulaire.
Dans l’absolu nous n’avons pas besoin de passer la collection à cette vue. Nous le faisons uniquement pour bénéficier de la facilité du create.
Cela s’apparente à ce qu’on pourrait faire dans le cadre d’une association en Ruby on Rails (par exemple @category.products.create).
On pourrait toutefois s’en passer en faisant une initialisation classique du model (new, save).
Dans notre vue nous avons introduit la notion d’évènements.
La syntaxe se fait tout simplement sous forme d’un hash avec d’une part l’évènement et le sélecteur et d’autre part la fonction à appeler. L’évènement concerné sera systématiquement passé à cette fonction.
Notre premier évènement va permettre de détecter les frappes dans notre input et appeler saveNewCategoryIfSubmit
en retour.
Dans cette fonction nous allons tester si c’est ou non la touche entrée qui est utilisée. Si c’est le cas, nous lançons la création de données.
Nous faisons exactement la même chose lorsque nous cliquons sur le bouton.
Dans cette partie nous allons voir comment créer des données tout en utilisant les validations de notre couche client.
La partie création de données se résume à ces deux lignes:
attributes = { category: { name: $("#category_name").val() } }
@collection.create(attributes, { error: @showErrors })
Pour récupérer nos valeurs nous utilisons simplement la méthode val() de jQuery. Le create de la collection utilise l’url que nous avons définie dans cette dernière pour poster les données.
Le deuxième argument est un hash de définition des callbacks. En cas d’erreur c’est la méthode showErrors qui sera appelée.
Ce callback va nous passer deux paramètres: l’objet et les erreurs. Comme nous avons déjà préparé nos erreurs sous forme de string il nous reste juste à les insérer dans la zone de messages, en l’ayant vidée au préalable.
Notre dernier évènement focusout va automatiquement vider la zone de message quand nous allons retirer le focus du champ.
Les validations par la couche serveur sont indispensables. Mais dans le cadre d’une application riche, ce n’est pas du luxe d’ajouter des validations clientes afin de d’avoir un retour immédiat.
Cela augmentera le sentiment de vitesse et de confort de l’application.
Pour faire de la validation côté client, backbone.js nous mets à disposition une
méthode validate
, libre à nous d’implémenter son contenu.
Validate nous passe les attributs en paramètres, mais attention, uniquement les paramètres qui ont été modifiés.
Les attributs de l’objet sont eux stockés dans @attributes
. Nous allons donc
travailler sur un merge des deux pour passer nos validations.
Pour éviter de merger dans l’une des deux variables nous allons cloner les attributs de l’objet d’abord en utilisant les méthodes de underscore.js.
class Category extends Backbone.Model
validate: (attributes) ->
mergedAttributes = _.extend(_.clone(@attributes), attributes)
if !mergedAttributes.name or mergedAttributes.name.isBlank()
return "Name can't be blank."
Désormais le create va appeler les validations sur le modèle. Il y a très peu de choses à appeler dans notre vue, le même callback du create sera utilisé avec les mêmes paramètres.
Nous allons juste l’adapter pour utiliser soit responseText si la réponse vient du serveur, soit directement errors.
showErrors: (model, errors) =>
content = errors.responseText || errors
@emptyMessages()
$("#messages").html(content)
Pour en terminer avec cette partie une étape importante est de recharger automatiquement notre liste à l’ajout d’un item.
C’est là qu’on s’aperçoit de toute la puissance de Backbone.js. Il va nous suffire d’être à l’écoute du add sur la collection pour refaire un rendu de la liste.
initialize: ->
_.bindAll(@, 'render')
@collection.bind 'reset', @render
@collection.bind 'add', @render
J’espère que cette partie vous aura aider à mieux appréhender les concepts et la manière d’utiliser Backbone.js.
Si vous souhaitez que nous allions plus loin, n’hésitez pas à nous en faire part dans les commentaires.
L’équipe Synbioz.
Libres d’être ensemble.
Nos conseils et ressources pour vos développements produit.