2012-12-30 14 views
6

Supponendo che ho una struttura di dati come questo:ricorsione con doT.js

{ list: [ { 
     name: "1", 
     children: [{ 
       name: "1.1", 
       children: [] 
      }, 
      { 
       name: "1.2", 
       children: [{ 
        name: "1.2.1", 
        children: [] 
        } 
       ] 
      } 
     ] 
     }, 
     { 
     name: "2", 
     children: [{ 
       name: "2.1", 
       children: [{ 
        name: "2.1.1", 
        children: [] 
        },   
        { 
        name: "2.1.2", 
        children: [] 
        },    
        { 
        name: "2.1.3", 
        children: [] 
        } 
       ] 
      }, 
      { 
       name: "2.2", 
       children: [] 
      }, 
      { 
       name: "2.3", 
       children: [] 
      } 
     ] 
     }, 
     { 
     name: "3", 
     children: [{ 
       name: "3.1", 
       children: [] 
      } 
     ] 
     } 
    ] 
} 

Come potrei fare per la creazione di un modello con doT.js che ricorsivamente passare attraverso l'oggetto e costruire liste annidate?

Costruire la stringa di codice HTML direttamente in JS con una funzione ricorsiva è dritto abbastanza avanti: (http://jsfiddle.net/fergal_doyle/WN8hZ/5/)

var html = ""; 
function buildList(a){ 

    if (a.length == 0){return}; 

    html += "<ul>"; 
    for (var i = 0; i < a.length; i++) 
    { 
     html += "<li>" + a[i].name; 
     buildList(a[i].children); 
     html += "</li>"; 
    } 
    html += "</ul>";    
} 
buildList(data.list); 

$("#out").html(html); 


Ma con doT.js questo è quello che ho e dopo che io sono perplesso ! (http://jsfiddle.net/fergal_doyle/BTZpu/4/)

EDIT: posso farlo mescolando in qualche JS con la valutazione (http://jsfiddle.net/fergal_doyle/he8AN/)

{{ function buildList(a) { }} 

    {{?a.length}} 
    <ul> 
     {{~a :v}} 
     <li> 
      {{=v.name}} 
      {{ buildList(v.children); }} 
     </li> 
     {{~}} 
    </ul> 
    {{?}} 

{{ } }} 

{{ buildList(it.list); }} 

stavo cercando di raggiungerlo con parziali. Definendo un ul snippet, lo snippet chiama se stesso passando un array come parametro, ma sto ricevendo un errore di "ricorsione troppo". Se c'è un modo per far funzionare il sotto, è molto più ordinato di quanto penso sopra. (http://jsfiddle.net/fergal_doyle/qazGe/4/)

{{##def.ul:a: 
    <ul> 
    {{~a :value}} 
     <li>{{=value.name}}{{#def.ul:value.children}}</li> 
    {{~}} 
    </ul> 
#}} 

{{#def.ul:it.list}} 

risposta

3

Il problema è in fase di compilazione. doT.js non sembra gestire la ricorsione in partial. Il codice di ricorsione {{#def.ul:value.children}} rende la libreria doT.js infinitamente risolvibile/sostituibile con il contenuto della tua funzione. Un modo per aggirare questo è usare arguments.callee per fare riferimento al tuo parziale all'interno del tuo parziale. Ecco un fork del vostro FIDDLE

{{##def.ul:a: 
    <ul> 
    {{~a :value}} 
    <li>{{=value.name}}{{=arguments.callee(value.children)}}</li> 
    {{~}} 
    </ul> 
#}} 

{{#def.ul:it}} 

L'autore (s) della biblioteca in grado di implementare la stessa idea nella loro biblioteca nel modo seguente (non testato):

function resolveDefs(c, block, def) { 
    return ((typeof block === 'string') ? block : block.toString()) 
    .replace(c.define || skip, function(m, code, assign, value) { 
     if (code.indexOf('def.') === 0) { 
      code = code.substring(4); 
     } 
     if (!(code in def)) { 

      // HANDLE RECURSION START 
      value = value.replace(c.use || skip, function(m, recursiveCode) { 
       if (c.useParams) return recursiveCode.replace(c.useParams, function(m, s, d, param) { 
        if(d == code) { 
         var ret = s + "{{=arguments.callee("; 
         if(param) 
          ret += param; 
         return ret + ")}}"; 
        } 
       }); 

      }) 
      // HANDLE RECURSION END 

      if (assign === ':') { 
...