2012-04-12 12 views
55

Recientemente he separado ViewModel a un archivo JavaScript por separado.Knockout disparando enlace de clic en applyBindings

var Report = (function($) { 
    var initialData = []; 
    var viewModel = { 
     reports: ko.observableArray(initialData), 
     preview: function(path) { 
      // preview report 
     }, 
     otherFunctions: function() {} 
    }; 
    return viewModel; 
})(jQuery);​ 

Aquí está el código HTML y relacionados Knockout

<script type="text/javascript" src="path/to/report/javascript"></script> 
<script type="text/javascript"> 
    $(document).ready(function() { 
     ko.applyBindings(Report, document.body); 
    }); 
</script> 

interfaz de usuario HTML tiene un botón en la cual clic es enlazar datos a la función de vista previa en el modelo de vista

<input type="button" name="Preview" id="Preview" class="btnPreview" 
    data-bind="click: Report.preview('url/to/report')" /> 

Problema método de vista previa se llama cuando la siguiente línea ejecutar en $ (document) ready() la función

ko.applyBindings(Report, document.body); 

es decir, sin el usuario haga clic en el botón de la función de vista previa vista previa se dispara. ¿Cuál podría ser el motivo de este comportamiento? Todo estaba funcionando bien cuando veía el modelo de JavaScript en la página HTML.

Respuesta

78

La razón es que, de hecho, está invocando la función de vista previa (porque escribir functionName significa referirse a la función, escribir functionName() significa llamarlo).

Así data-bind="click: Report.preview" estaría trabajando como se esperaba, pero sin entregar el parámetro.

Como the manual estados (sobre un tema diferente, pero esto todavía se aplica):

Si necesitas pasar más parámetros, una forma de hacerlo es envolviendo su controlador en un literal de la función que toma en un parámetro, como en este ejemplo:

<button data-bind="click: function(data, event) { myFunction(data, event, 'param1', 'param2') }"> 
    Click me 
</button> 

o en su caso:

data-bind="click: function() { Report.preview('url/to/report') }" 

Otra solución sería hacer vista previa() devuelven una función (más o menos la misma cosa en realidad):

preview: function(path) { 
    return function() { 
     // ... 
    } 
} 
+7

Me tomó un minuto obtener esta respuesta. La aclaración que necesitaba: es porque está llamando a 'Report.preview' con'() 'que ejecuta la llamada en lugar de devolver el puntero a la función. Sin corchetes funcionaría como se esperaba. – Peter

21

Otra solución es utilizar 'bind' construir:

data-bind="click: Report.preview.bind($data, 'url/to/report')" 

donde el primer parámetro para bind() se convertirá en 'this' en la función llamada.

Cuestiones relacionadas