2012-02-07 10 views
38

estoy usando la siguiente plantilla:Knockout.js - foreach vinculante - prueba si el elemento última

<div class="datatypeOptions" data-bind="if: $data.datatypeTemplate().allowOptions"> 
    <h3>Allowed responses</h3> 

    <p data-bind="if: $data.datatypeTemplate().datatypeOptions().length == 0">There are no responses for this question, yet. <a href="#" data-bind="click: function(d, e){$root.addDatatypeOption($data.datatypeTemplate());}">Add one</a> 
    <ul data-bind="foreach: $data.datatypeTemplate().datatypeOptions()"> 
     <li> 
      <a href="#" data-bind="text: name, click: $root.selectedDatatypeOption, visible: $data !== $root.selectedDatatypeOption()"></a> 
      <input data-bind="value: name, visibleAndSelect: $data === $root.selectedDatatypeOption(), event: { blur: $root.clearDatatypeOption }, executeOnEnter: { callback: function(){ $root.addDatatypeOption($parent.datatypeTemplate()); } }" /> 
      //I want to show this a tag only if $data is the last element in the array. 
Problem here ===> <a href="#" data-bind="if: $data == $parent.datatypeTemplate().datatypeOptions()[ $parent.datatypeTemplate().datatypeOptions().length - 1 ], click: function(d, e){$root.addDatatypeOption($data.datatypeTemplate());}"><img src='/static/img/icons/custom-task-wizard/black/plus_12x12.png' title='Add option'></a> 
     </li> 
    </ul> 
</div> 

me sale este error en la consola:

Uncaught Error: Unable to parse bindings. 
Message: TypeError: Object [object Object] has no method 'datatypeTemplate'; 
Bindings value: if: $data == $parent.datatypeTemplate().datatypeOptions()[ $parent.datatypeTemplate().datatypeOptions().length - 1 ], click: function(d, e){$root.addDatatypeOption($data.datatypeTemplate());} 

es mi única opción para añadir una función a mi modelo de vista que devuelve verdadero/falso si el elemento pasado es el último en la matriz?

+0

http://memegenerator.net/instance/14211604 – Jonathan

+2

Es posible que desee intentar reproducir esto en jsFiddle. Lo único que noté es que te falta un cierre de tu etiqueta 'p', que puede causar problemas en el enlace/contexto. Puede mantener su vista más limpia al poner un observable calculado o una función en su modelo de vista para ayudar a determinar el último elemento. –

Respuesta

0

intente lo siguiente:

  1. Uso $root en lugar de $parent
  2. Preparar el último elemento de avance y pasan este elemento a su plantilla como parámetro adicional.
  3. Encapsula el último elemento en observable.
73

He simplificado el problema, pero este jsFiddle demuestra una posible solución.

"si" vinculante:

<div data-bind="if: ($index() === ($parent.data().length - 1))">I'm the last element</div> 

Containerless "si" vinculante:

<!-- ko if: ($index() === ($parent.data().length - 1)) --> 
<div>I'm the last element again</div> 
<!-- /ko --> 

Usted puede utilizar $index dentro de un foreach vinculante para obtener el índice de la actualidad Objeto encuadernado Úselo para comparar con la colección original del padre.

Consulte HERE para obtener más información sobre los contextos vinculantes.

+1

Desafortunadamente, si usa la opción 'as',' $ data' no está enlazado ... solo un "gotcha". – user2246674

+0

Esto no funcionó para mí, creo que tal vez b/c Estoy en octava v 2.2.1. Sin embargo, lo siguiente funcionó (por supuesto, reemplace MyWingDings con el nombre de su objeto array). data-bind = "visible: $ index() <$ parent.MyWingDings.length - 1" – Sean

+0

@ user2246674 see ** [mi respuesta] (http://stackoverflow.com/a/076/4390133) ** en el estuche estás usando la opción 'as' –

8

me di cuenta de que hay una serie de solicitudes de mejoras en KO para apoyar las $length, $last o $array propiedades reservadas en la unión foreach aunque, por una variedad de razones (a menudo de rendimiento), que no han logrado entrar en el código base

Si alguien está interesado en exponer estos elementos para un caso específico utilizando un enlace personalizado, aquí hay un ejemplo simple de exposición de la variable $length para imprimir una lista "bonita".
Simplemente use forEachWithLength en cualquier lugar que normalmente usaría foreach.uso

ko.bindingHandlers.forEachWithLength = { 
    init: function (element, valueAccessor, allBindingsAccessor, viewModel, context) 
    {   
     return ko.bindingHandlers.foreach.init(element, valueAccessor, allBindingsAccessor, viewModel, context); 
    }, 
    update: function (element, valueAccessor, allBindingsAccessor, viewModel, context) 
    {   
     var array = ko.utils.unwrapObservable(valueAccessor()); 
     var extendedContext = context.extend({"$length" : array.length }); 
     ko.bindingHandlers.foreach.update(element, valueAccessor, allBindingsAccessor, viewModel, extendedContext); 
    } 
}; 

Ejemplo:

<div data-bind="forEachWithLength: myArray"> 
    <span data-bind="text: $data"></span> 
    <!-- ko if: ($index() < $length-2) -->, <!-- /ko --> 
    <!-- ko if: ($index() === $length-2) --> and <!-- /ko --> 
</div> 

de entrada:["One", "Two", "Three", "Four"]

de salida:One, Two, Three and Four

Fiddle

Further reading

2

Si usted es NO usando as opción en el foreach vinculante, y luego ir a la most-upvoted answer to this question.

Si es DO usando el operador as en el enlace foreach. entonces esa respuesta será NOT trabajo.

Aquí está la solución en ese caso

<div data-bind="foreach:{data: Items, as :'item'}"> 
    <div data-bind="if: ($index() === ($parent.Items().length - 1))">I'm the last element</div> 
</div> 

El secreto con la sustitución de la $parent.data() con el nombre de la matriz observable está utilizando En mi caso, fue nombrado Items, así que sustituyó a la $parent.data() con $parent.Items()

NOTAesta solución está trabajando en todos los casos, en caso de que esté utilizando as opción o sin t,
pero en el primer caso resuelve algo que la respuesta más actualizada no resolvió

Cuestiones relacionadas