开发者

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:

  1. add the Discrepancy property to the Product class, with default 0. Throw away the ComputeDiscrepancy stuff.

  2. write a couple of functions that take note of changes in InStock and Ordered. These will update the relevant properties of the target object and then call a function called calcDiscrepancy and return its return value.

  3. calcDiscrepancy will update the value to the target object's Discrepancy property. To ensure that all the events are triggered with this change, I used jQuery's .data() method.

  4. 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.

  5. 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 calls changeInStock, etc. For the Discrepancy property, the converter is a convertBack type that calls showDiscrepancy. (In essence convert goes from the DOM element to the object property, and convertBack goes from the property to the element.)

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜