2011-11-09 4 views
17

Sto utilizzando backbone.js e underscore.js per creare un'applicazione javascript. Dalle ore di lettura e cercando di eseguire un modello all'interno di un modello come di seguito, sta diventando sempre più frustrante.Esegui modello nel modello (ricorsione) all'interno del motore di template underscore.js

mio modello utilizzando la configurazione in template engine underscore.js:

<script id="navigation_template" type="text/template"> 
    <div><%= title %> 
     <% _.each(children, function(child) { %> 
      <% render_this_template_recursively(child) %> 
     <% }); %> 
    </div> 
</script> 

vorrei rendere questo modello per ogni elemento figlio (render_this_template_recursively (bambino)).

Come posso fare questo?

Grazie

+1

heeeeey, che è piuttosto una domanda interessante ... Hai provato la risposta qui sotto? ;) –

+1

Hey Adam, hai lavorato? O hai usato qualcos'altro? –

+1

@ jamie-wilson Ho ottenuto qualcosa che ha ispirato la risposta di Ashish Datta. Ho pubblicato un esempio minimalista di seguito. –

risposta

34

non ho provato personalmente questo, ma _.template restituisce una funzione (che ho chiamato è templateFn sottolineare che), così si potrebbe passare nel template in questo modo:

var templateFn = _.template($('#navigation_template').html()); 

$(this.el).html(templateFn({model: this.model, templateFn: templateFn})); 

si noti che sto passando l'intero modello (supponendo che il modello ha una proprietà dei bambini, che è di per sé una collezione di modelli di backbone) e il modello sarebbe cambiato a:

<script id="navigation_template" type="text/template"> 
    <div><%= model.escape('title') %> 
     <% _.each(model.children, function(child) { %> 
      <%= templateFn(child, templateFn) %> 
     <% }); %> 
    </div> 
</script> 

Buona fortuna. Spero che questo funzioni per voi

+0

Grazie! ottima risposta –

+0

@timDunham cosa devo fare se sto usando un plug-in di testo per caricare i template. dovrei fare templateFn = _.template ($ ('# navigation_template'). html()); – asdfdefsad

+0

'<% = templateFn (child, templateFn)%>' non funziona per me. Ma funziona perfettamente '<% = templateFn ({model: child, templateFn: templateFn})%>' – Londeren

8

Ho appena provato con successo questo. L'ho provato con solo UnderscoreJS puro, senza BackboneJS ma funzionalmente non dovrebbe avere importanza.

Ecco il codice:

<!DOCTYPE html> 
<html lang="en"> 
    <head> 
    <meta charset="utf-8"> 
    <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script> 
    <script type="text/javascript" src="underscore.js"></script>  
<style> 

.container { 
    position: relative; 
    margin-bottom: 20px; 
} 

#container { 
    position: relative; 
    margin: auto; 
} 

.fib-box { 
    position: absolute; 
    top: 0px; 
    left: 0px; 
    background: rgba(0,68,242,0.15); 
    border: 1px solid rgba(0,0,0,0.20); 
} 

.header { 
    padding-bottom: 10px; 
} 

</style> 
    </head> 
    <body> 

    <div class="header"> 
     <h3>Render Fibonacci With UnderscoreJS</h3> 
     <form id="updateCount"> 
      <input type="text" value="13" id="fibSequence" /> 
      <input type="submit" value="Update" /> 
     </form> 
    </div> 

    <div class="container"> 
    <div id="container"> 

    </div>  
    </div> 

<script type="text/template" id="template"> 
<% if(depth){ %> 
<div class='fib-box' data-depth='<%= depth %>' style='width: <%= val %>px; height: <%= val %>px;'></div> 
<% print(template(getFibObj(depth-1))) %> 
<% } %> 
</script> 

<script type="text/javascript"> 

var template; 

$(document).ready(function(){ 

    template = _.template($("#template").text()); 

    $("#updateCount").submit(function(){ 

     $("#container").html(template(getFibObj($("#fibSequence").val()))); 

     var width = $("#container .fib-box:first").css("width"); 
     $("#container").css({width: width, 'min-height': width}); 

     return false; 
    }); 

    $("#updateCount").submit(); 
}); 

function getFibObj(i){ 
    return {depth: i, val: fib(i)}; 
} 

function fib(i){ 
    return (i == 0 || i == 1) ? i : fib(i-1) + fib(i-2); 
} 

</script> 

    </body> 
</html> 
+2

Bel lavoro sul codice demo! –

+0

@Ashish Datta è possibile utilizzare questo approccio con il tipo di oggetto viewmodel. come l'elaborazione dei dati dovrebbe essere fatta in viewmodel e poi passarla al template per ogni ricorsione. – asdfdefsad

+0

@JSBin non sono sicuro di seguire il 100% ma potresti sicuramente costruire i blocchi HTML nel tuo controller e poi passare tutto ciò nel tuo template? –

1

Un modello ricorsivo può essere simile a questa:

<ul> 
    <% entries.forEach(function (entry) { %> 
    <li> 
     <%= entry.title %> 
     <% 
     if (entry.children) { 
      print(tmpl({ 
       entries: entry.children, 
       tmpl: tmpl 
      })); 
     } 
     %> 
    </li> 
    <% }); %> 
</ul> 

In primo luogo, pre-compilare il modello:

entriesTmpl = _.template(entriesTmpl); 

Poi chiamare passando sia i dati che il modello stesso:

$el.html(entriesTmpl({ 
    entries: entryTree, 
    tmpl: entriesTmpl 
}); 
5

Ho provato ad usare l'esempio presentato da timDunham e Ates Goral, ma non ha funzionato per me, quindi ho fatto un piccolo aggiornamento per questo. Trovalo qui sotto.

vista:

template: _.template($("#tree").html()), 

    render: function() { 
     this.$el.html(this.template({ 
      options: this.collection.toJSON(), 
      templateFn: this.template 
     })); 
    } 

e il modello:

<script type="text/template" id="tree"> 
<ul> 
    <% _.each(options, function (node) { %> 
     <li><%= node.title %></li> 
     <% if (node.children) { %> 
      <%= templateFn({ options: node.children, templateFn: templateFn }) %> 
     <% } %> 
    <% }); %> 
</ul> 

E funziona abbastanza bene per me. La differenza principale, come puoi vedere, è l'oggetto di configurazione che passa in templateFn, invece di argomenti. Spero che lo troverai utile

+0

è possibile utilizzare questo approccio con il tipo di oggetto viewmodel. come l'elaborazione dei dati dovrebbe essere fatto in viewmodel e quindi passarlo al modello per ogni ricorsione. – asdfdefsad

0

L'ho implementato recentemente utilizzando il backbone-relazionale. Ho creato un violino che pensavo potesse essere utile se vuoi vedere una soluzione funzionante: http://jsfiddle.net/blaisco/ADKrK/

Ho postato i bit rilevanti di seguito.

La vista:

var FolderView = Backbone.View.extend({ 
    el: $("#main"), 

    template: _.template($("#folder-tmpl").html()), 

    render: function() { 
     this.$el.html(this.template({ 
      "folder": parentFolder.toJSON(), 
      "templateFn": this.template 
     })); 
     return this; 
    } 
}); 

il codice HTML/modello:

<ul id="main"></ul> 

<script type="text/template" id="folder-tmpl"> 
    <li> 
     <a href="#" class="folder"><%= folder.title %></a> 
     <% if(folder.children.length) { %><ul><% } %> 
     <% _.each(folder.children, function(child) { %> 
      <%= templateFn({"folder": child, "templateFn": templateFn}) %> 
     <% }); %> 
     <% if(folder.children.length) { %></ul><% } %> 
    </li> 
</script> 
+0

è possibile utilizzare questo approccio con il tipo di oggetto viewmodel. come l'elaborazione dei dati dovrebbe essere fatto in viewmodel e quindi passarlo al modello per ogni ricorsione – asdfdefsad