2013-07-24 19 views
12

Ho questa mappatura ad eliminazione diretta che il mio array ha ricevuto dalla chiamata ajax di seguito.Limit foreach loop knockout

function InvoiceViewModel(data) { 
var self = this; 

self.survey = data; 

} 

Ajax chiamata

$.ajax({ 
    url: 'http://localhost:43043/api/damage', 
    type: 'GET', 
    headers: { 'Accept': 'application/json' }, 
    data: { 
     orderNumber: num, 
     category: cat 
    }, 
    success: 
      function (data) { 
       var usingRoutData = document.URL; 
       ko.applyBindings(new InvoiceViewModel(data)); 
      }, 

    error: function() { 
     alert('failure'); 
    } 

}); 

mio Array

var test = { 
    Name: Blah, 
    Attributes: [ 
       {Name: Test, Type: Photo, Year:1988}, 
       {Name: Test, Type: Photo, Year:1988}, 
       {Name: Test, Type: Photo, Year:1988} 
       ] 
      }; 

Come sto forza vincolante miei dati

<div id="invoiceBodyWrapper"> 
<div data-bind="template: { name: 'invoice-template', foreach: surveys }"> 
</div> 

<div class="invoiceWrapper"> 
    </div> 
    <div id="completePictureWrapper" data-bind="template: { name: 'photo-template',  foreach: new Array(Attributes) }"></div> 

</div> 
</script> 

<script type="text/html" id="photo-template"> 
<!-- ko if: classification === 'photo' --> 
<div id="pictureWrappers"> 
    <img class="img" data-bind="attr: { src: 'http://myimagepath/download/full/' + $index()+1 }" /> 
</div> 
<!-- /ko --> 
</script> 
    <script src="~/Scripts/DamageInvoiceCreation.js"></script> 

Ho bisogno di un modo per limitare il mio ciclo foreach di attributi solo per mostrare 2 dei 3 attributi. Ho solo trovato alcune cose su come farlo e sembrano molto complicate. Non riesco a immaginare che non ci sia un modo semplice per farlo a eliminazione diretta.

+0

Non v'è alcun ciclo nel tuo post. Come sei vincolante per la tua visione? – Romoku

+1

Hai visto [Knockout.js - Colonne dinamiche ma limitato a un massimo di 5 per ogni riga] (http://stackoverflow.com/q/7669946/580951) – Romoku

+0

@Romoku molto da imparare in questa domanda, ma c'è codice sicuramente applicabile. Buon collegamento! –

risposta

0

è possibile limitare un ciclo in questo modo:

for(var i=0;i<data.length;i++){ 
    if(i>1){ 
     return false; 
    } 
} 
+0

puoi aggiungere un contesto a questo. Inoltre non è l'intero array che vorrei limitare solo il sub-array – EntryLevel

+1

Quindi fare questo solo per l'array secondario. sostituire i dati con i dati.Attributi –

7

Se avete sempre 3 attributi e sempre e solo desidera mostrare 2 di loro, non c'è bisogno di foreach loro, esattamente.

Tuttavia, vi è la variabile di contesto di rilegatura speciale $index(), che consente di eseguire alcune operazioni di base, anche se non impedisce il rendering. Poiché l'indice $ è basato su 0, la condizione è $index() < 2. Come osserva Andrey nei commenti, $index is an observable, quindi devi chiamarlo con le parentesi come metodo, o i confronti non faranno quello che ti aspetti (comparirai un int contro una funzione).

<ul data-bind="foreach: survey.Attributes"> 
    <li data-bind="visible: $index() < 2"> 
     Name: <span data-bind="text: Name"> </span><br/> 
     Type: <span data-bind="text: Type"> </span><br/> 
     Year: <span data-bind="text: Year"> </span><br/> 
    </li> 
</ul> 

Se si desidera un limitatore generico su un ciclo foreach, hai ragione, non è semplice. Dovresti creare un numero custom binding.

Un altro approccio che è possibile considerare è il pre-elaborazione dei dati in viewmodel. Quando si imposta this.survey = data;, è possibile rimuovere qualsiasi attributo che non si desidera visualizzare in quel punto.

Modifica: Vedo dal vostro edit che si conoscono gli elementi psuedo ko: if. Mi sono completamente dimenticato di questi, ma potresti facilmente usarne uno per impedire il rendering degli elementi del modello oltre un determinato indice. Il foreach valuterà comunque l'osservabile, che non dovrebbe avere alcun tipo di enorme sovraccarico da solo.

+1

Penso che tu intenda '$ index()'. '$ index <3' restituirà sempre false http://jsfiddle.net/aDahT/1087/ –

+0

Ovviamente hai ragione, @AndreyNelubin, ha aggiornato la risposta. –

+0

Questa è di gran lunga una delle più belle soluzioni a questo problema, se vuoi solo mostrare 2 attributi che dovresti usare <2 [0 è anche un numero :)] –

5

array JavaScript includono l'eccellente metodo di slice che dovrebbe riempire il vostro bisogno piacevolmente:

template: { name: 'photo-template', foreach: Attributes.slice(0,2) } 

Ma, come @ Patrick-M accennato, non è necessario un ciclo:

template: { name: 'photo-template', data: Attributes[0] } 
template: { name: 'photo-template', data: Attributes[1] } 

mio Repeat vincolante include un'opzione per limitare il numero di ripetizioni:

<div data-bind="repeat: { foreach: Attributes, count: 2 }" 
     data-repeat-bind="template: { name: 'photo-template', data: $item() }"> 
</div> 
0

Ho risolto un problema simile spingendo un sottoinsieme degli elementi dell'array originale in un altro array nel mio viewmodel, quindi legandolo all'array dei sottoinsiemi.

+0

Penso che a volte le persone diventano "troppo ambiziose" con KO e buttano anche loro molto JS nel codice HTML. Questa è una soluzione abbastanza logica. Non fraintendermi, non c'è niente di sbagliato in KO, è un grande lib di UI. –

3

È possibile creare calcolata con il limite di serie limitata:

var limited = ko.computed(function() { 
    return Attributes.slice(0, limit); 
}); 

Poi tutto quello che dovete fare per foreach limitato. È anche possibile aggiungere somekind di elemento "di più":

<!-- ko if: Attributes().length > limit --> 
    <div class="more">...</div>   
<!--/ko--> 

spero che sarà utile per ulteriori generazioni;)

Problemi correlati