문제

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",
           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.)

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top