smart | Webentwicklung
Alles rund um HTML5, PHP, WordPress & Co.

Ruby on Rails & backbone.js: JavaScript-Templates nutzen

9. Juli 2012
Stephan
Ruby on Rails & backbone.js: JavaScript-Templates nutzen

Für diejenigen von euch, die in ihren Ruby on Rails Applikationen für das Strukturieren des clientseitigen JavaScript-Codes backbone.js einsetzen (hierfür gibt es auch eine Erweiterung (Gem) mit der Scaffolding möglich ist: Backbone-Rails), zeige ich im Folgenden, wie ihr JavaScript-basierte Templates nutzen könnt.

Diese sogenannten EJS-Templates bzw. JST-Templates werden mithilfe der Erweiterung Ruby-EJS verarbeitet, welche ab Rails 3.1 standamäßig an Bord ist. Diese Erweiterung ist generell nichts weiter als eine Portierung der underscore.js-_.template-Funktion.

Zur Info: Der folgende Artikel und die hier vorgestellten Code-Auszüge basieren auf Ruby on Rails 3.2 & backbone.js 0.9.2.

Template in Backbone-View definieren

Um in einer Backbone-View auf ein Template zuzugreifen, kann innerhalb der View ein Template wie folgt definiert werden:

var AnswerListItemView = Backbone.View.extend({
    template: JST['app/templates/answers/listItem']
});

Wie ihr sehen könnt, geben wir einfach den Pfad zu unserem Template an. Dabei gehen wir davon aus, dass unser JavaScript-Verzeichnis in etwa so strukturiert ist:

Ruby on Rails & backbone.js - JavaScript-Verzeichnis

Damit das Template von der Asset-Pipeline geladen wird, müssen wir es in unserer application.js hinzufügen:

//= require app/templates/answers/listItem

Anschließend können wir das Template „rendern“:

var AnswerListItemView = Backbone.View.extend({
    template: JST['app/templates/answers/listItem'],

    render: function(isEditMode)
    {
        this.$el.html(this.template({
            answer: this.model, 
            isEditMode: isEditMode})
        );
    }
});

Wie ersichtlicht ist, können wir dem Template auch Parameter mit übergeben.

Grundsätzlich müssen wir unser Template auch nicht erst einer Variable zuweisen (aus Gründen der Übersichtlichkeit aber anzuraten), sondern können direkt darauf zugreifen:

JST['app/templates/general/messageBox'](params)
var AnswerListItemView = Backbone.View.extend({
    render: function(isEditMode)
    {
        this.$el.html(JST['app/templates/answers/listItem']({
            answer: this.model, 
            isEditMode: isEditMode})
        );
    }
});

Template erstellen

Basierend auf dem obigen Code, erstellen wir nun unser Template. Dazu legen wir als erstes eine Template-Datei namens listItem.jst.ejs im Verzeichnis app/templates/answers/ an.

Zu den Template-Dateiendungen: jst: JavaScript-Template, ejs: Embedded JavaScript

Danach kann der nötige Template-Code eingefügt werden – beispielsweise:

<div class="head">
    <% var answerTranslation = I18n.t('activerecord.models.answer'); %>
    <%= answerTranslation %> <%= answer.get('position') + 1 %>
    <div class="links">
        <span class="editLink"
            title="<%= I18n.t('views.general.crud_links.edit', {model_name: answerTranslation}) %>"></span>
        <span class="deleteLink"
            title="<%= I18n.t('views.general.crud_links.delete', {model_name: answerTranslation}) %>"></span>
        <span class="sortLink"
            title="<%= I18n.t('views.general.crud_links.sort', {model_name: answerTranslation}) %>"></span>
    </div>
</div>
<div class="details">
    <span class="kind">
        <% if(!isEditMode) { %>
            <% if(answer.get('kind') == 0) { %>
                <%= I18n.t('views.answer.kind.correct') %>
            <% } else if(answer.get('kind') == 1) { %>
                <%= I18n.t('views.answer.kind.doubtful') %>
            <% } else { %>
                <%= I18n.t('views.answer.kind.incorrect') %>
            <% } %>
        <% } else { %>
            <% var checked = ' checked="checked"'; %>
            <input type="radio" value="<%= answer.KIND_CORRECT %>" name="kind<%= answer.id %>"<%= answer.get('kind') == 0 ? checked : '' %> /> <%= I18n.t('views.answer.kind.correct') %>
            <input type="radio" value="<%= answer.KIND_DOUBTFUL %>" name="kind<%= answer.id %>"<%= answer.get('kind') == 1 ? checked : '' %> /> <%= I18n.t('views.answer.kind.doubtful') %>
            <input type="radio" value="<%= answer.KIND_INCORRECT %>" name="kind<%= answer.id %>"<%= answer.get('kind') == 2 ? checked : '' %> /> <%= I18n.t('views.answer.kind.incorrect') %>
        <% } %>
    </span>
</div>
<div class="text">
    <% if(!isEditMode) { %>
        <%= answer.get('text') %>
    <% } else { %>
        <textarea class="textTextarea"><%= answer.get('text') %></textarea>
        <input type="button"
            value="<%= I18n.t('views.general.crud_links.update', {model_name: answerTranslation}) %>"
            class="saveButton" />
        <input type="button"
         value="<%= I18n.t('views.general.abort') %>"
         class="cancelButton" />
    <% } %>
</div>

Inerhalb des Templates kann direkt auf die übergebenen Variablen zugegriffen werden. Wer sich fragt, was es mit der I18n.t-Funktion auf sich hat, den verweise ich auf meinen Artikel: Ruby on Rails – I18n-Übersetzungen in JavaScript benutzen.

Generell besteht ein solches JavaScript-Template aus reinem HTML-Code der mit JavaScript-Code „angereichert“ wird (ähnlich den serverseitigen ERB-Views).

Wenn wir JavaScript-Code ausführen möchten, dann packen wir diesen Code innnerhalb <% %> und <%= %> dient der Interpolation von Variablen. HTML-Escaped-Ausgaben sind mit <%- %> möglich.

Fazit

Mit backbone.js und den vorgestellten JavaScript-Templates haben wir eine einfache Möglichkeit unseren clientseitigen JavaScript-Code unserer Ruby on Rails Applikationen noch weiter zu strukturieren.

Hierdurch lässt sich noch einfacher die Logik der Backbone-Views und die reine Repräsentation der Daten trennen, wodurch der Code einfach übersichtlicher wird, auch wenn auf der anderen Seite zum Teil mehr Overhead produziert wird.

Was haltet ihr von der vorgestellten Template-Funktion? Habt ihr sie schon mal verwendet oder setzt ihr andere Techniken in euren Ruby on Rails Applikationen ein?

Kommentare  
0 Kommentare vorhanden
0 Trackbacks/Pingbacks vorhanden
Du bist herzlich eingeladen auch ein Kommentar zu hinterlassen!
Kommentar schreiben

Vielen Dank für dein Kommentar!