jQuery Datalink not working with object methods
I have a javascript object with several properties. The object also contains an instance method that returns the result of a calculation on two of the object's properties.
I'm using the new Jquery .link() plugin (http://api.jquery.com/link/), to update the UI and form elements with the object property values and vice versa, whenever either the form or the object is updated.
This is all working except for one of the form elements, which should contain the result of the object's instance method but never gets updated.
I've put a button on the form to manually check the value of Discrepancy, and this works but the jquery link plugin is not populating the input elements automatically, although it is populating the input elements linked to the object properties. All elements have an id and name attributes.
Can anyone tell me where I'm going wrong?
My javascript:
<script>
function Product() {
this.InStock = 0;
this.Ordered = 0;
}
// object's instance method
Product.prototype.Discrepancy = ComputeDiscrepancy;
function ComputeDiscrepancy() {
return this.InStock - this.Ordered;
}
$(document).ready(function () {
var products = new Array();
products[0] = new Product();
products[1] = new Product();
$("form").link(products[0], {
InStock: "product0_InStock"开发者_JS百科,
Ordered: "product0_Ordered",
Discrepancy: "product0_Discrepancy"
});
$("form").link(products[1], {
InStock: "product1_InStock",
Ordered: "product1_Ordered",
Discrepancy: "product1_Discrepancy"
});
// button for me to manually check discrepancy method works
$("#checkData").click(function () {
alert(products[0].InStock);
$("#product0_Discrepancy").val(products[0].Discrepancy());
});
}); </script>
HTML:
<table>
<tr>
<th></th><th>Product 1</th><th>Product 2</th>
</tr>
<tr>
<td> In Stock</td>
<td><input id="product0_InStock" name="product0_InStock"/></td>
<td><input id="product1_InStock" name="product1_InStock"/></td>
</tr>
<tr>
<td>Ordered</td>
<td><input id="product0_Ordered" name="product0_Ordered"/></td>
<td><input id="product1_Ordered" name="product1_Ordered"/></td>
</tr>
<tr>
<td>Discrepancy</td>
<td><input id="product0_Discrepancy" name="product0_Discrepancy"/></td>
<td><input id="product1_Discrepancy" name="product1_Discrepancy"/></td>
</tr>
</table>
The problem is that Discrepancy is a method of a Product object and not a property. You can't link a DOM element to a method, only to a property.
The way I solved the problem is to (a) make Discrepancy a property, and (b) use the convert and convertBack methods in order to ensure that this new property was updated properly.
Here's my script block:
function Product() {
this.InStock = 0;
this.Ordered = 0;
this.Discrepancy = 0;
}
var products = [];
$(document).ready(function () {
products[0] = new Product();
products[1] = new Product();
var calcDiscrepancy = function(value, source, target) {
$(target).data("Discrepancy", target.InStock - target.Ordered);
return value;
};
var changeInStock = function (value, source, target) {
target.InStock = value;
return calcDiscrepancy(value, source, target) ;
};
var changeOrdered = function (value, source, target) {
target.Ordered = value;
return calcDiscrepancy(value, source, target) ;
};
var showDiscrepancy = function(value, source, target) {
$(target).text(value.toString());
};
$("form").link(products[0], {
InStock: {
name: "product0_InStock",
convert: changeInStock
},
Ordered: {
name: "product0_Ordered",
convert: changeOrdered
},
Discrepancy: {
name: "product0_Discrepancy",
convertBack: showDiscrepancy
}
});
$("form").link(products[1], {
InStock: {
name: "product1_InStock",
convert: changeInStock
},
Ordered: {
name: "product1_Ordered",
convert: changeOrdered
},
Discrepancy: {
name: "product1_Discrepancy",
convertBack: showDiscrepancy
}
});
});
Going through it:
add the
Discrepancy
property to theProduct
class, with default 0. Throw away the ComputeDiscrepancy stuff.write a couple of functions that take note of changes in
InStock
andOrdered
. These will update the relevant properties of the target object and then call a function calledcalcDiscrepancy
and return its return value.calcDiscrepancy
will update the value to the target object'sDiscrepancy
property. To ensure that all the events are triggered with this change, I used jQuery's.data()
method.write a
showDiscrepancy
method that would update the target's contents with the value passed in (the target is going to be the DOM element). I also changed the "discrepancy" elements to rather than text boxes: it didn't make sense otherwise.The calls to
link()
now map the relevant DOM elements to the relevant properties and specify converters for each. For the InStock property the converter is a convert type and callschangeInStock
, etc. For the Discrepancy property, the converter is a convertBack type that callsshowDiscrepancy
. (In essenceconvert
goes from the DOM element to the object property, andconvertBack
goes from the property to the element.)
精彩评论