2017-01-11 5 views
0

Ich kann nicht herausfinden, was dieser Fehler in meiner Geige bedeutet. Setzen Sie den Cursor auf die letzte Eingabe in der letzten Zeile und fahren Sie fort. Es soll eine neue Zeile hinzufügen. Aber irgendwo in meinem Code ist ein Fehler. Der Fehler, den ich bekomme, ist TypeError: itemNo(...) is undefined. Hier ist meine Geige: https://jsfiddle.net/tLfezuu1/1/Knockout Fehler in Geige

HTML:

<table class="table table-bordered table-striped" id="brochureItems"> 
    <thead> 
     <tr> 
      <th> 
       Item No 
      </th> 
      <th> 
       Bro Code 
      </th> 
      <th width="36%"> 
       Desc 
      </th> 
      <th width="15%"> 
       Retail 
      </th> 
      <th> 
       Prize Cnt 
      </th> 
      <th> 
       Order 
      </th> 
      <th> 
       Remove 
      </th> 
     </tr> 
    </thead> 
    <tbody data-bind="foreach: items"> 
     <tr> 
      <td> 
       <div data-bind="if: (itemNo().length < 1)"><input data-bind="value: itemNo, hasFocus: invalidItem(), selected: invalidItem(), event: { blur: $parent.checkItemNo }, attr: { name: 'brochureitems[' + $index() + '].itemNo', id: 'brochureItems_' + $index() + '__itemNo' }, validationOptions: { errorElementClass: 'input-validation-error' }" class="form-control item-id" /></div> 
       <div data-bind="if: (itemNo().length > 0)"><input data-bind="value: itemNo, attr: { name: 'brochureitems[' + $index() + '].itemNo', id: 'brochureItems_' + $index() + '__itemNo' }, validationOptions: { errorElementClass: 'input-validation-error' }" class="form-control item-ID" readonly="readonly" tabindex="-1" /></div> 
      </td> 
      <td> 
       <div data-bind="if: (brocCode.length < 1)"> 
        <input data-bind="value: brocCode, insertPress: $index, attr: { name: 'brochureitems[' + $index() + '].brocCode', id: 'brochureItems_' + $index() + '__brocCode' }, validationOptions: { errorElementClass: 'input-validation-error' }" class="form-control" /> 
       </div> 
       <div data-bind="if: (brocCode.length > 0)"> 
        <input data-bind="value: brocCode, insertPress: $index, attr: { name: 'brochureitems[' + $index() + '].brocCode', id: 'brochureItems_' + $index() + '__brocCode' }, validationOptions: { errorElementClass: 'input-validation-error' }" class="form-control" readonly="readonly" tabindex="-1" /> 
       </div> 
      </td> 
      <td class="item-desc"> 
       <input data-bind="value: itemDesc, attr: { name: 'brochureitems[' + $index() + '].itemDesc', id: 'brochureItems_' + $index() + '__itemDesc' }, validationOptions: { errorElementClass: 'input-validation-error' }" class="form-control" readonly="readonly" tabindex="-1" /> 
      </td> 
      <td class="item-retail"> 
       <div class="input-group"> 
        <div class="input-group-addon">$</div> 
        <div data-bind="if: ($index() === ($parent.items().length - 1))"><input data-bind="value: retail, valueUpdate: 'afterkeydown', attr: { name: 'brochureitems[' + $index() + '].retail', id: 'brochureItems_' + $index() + '__retail' }, validationOptions: { errorElementClass: 'input-validation-error' }, style: { backgroundColor: retail == 0 ? '#FFFCCE' : '#ffffff'}" class="form-control" /></div> 
        <div data-bind="if: ($index() < ($parent.items().length - 1))"><input data-bind="value: retail, valueUpdate: 'afterkeydown', money: retail, attr: { name: 'brochureitems[' + $index() + '].retail', id: 'brochureItems_' + $index() + '__retail' }, validationOptions: { errorElementClass: 'input-validation-error' }, style: { backgroundColor: retail == 0 ? '#FFFCCE' : '#ffffff'}" class="form-control" readonly="readonly" tabindex="-1" /></div> 
       </div> 
      </td> 
      <td> 
       <div><input data-bind="value: prizeNum, valueUpdate: 'afterkeydown', attr: { name: 'brochureitems[' + $index() + '].prizeNum', id: 'brochureItems_' + $index() + '__prizeNum' }, validationOptions: { errorElementClass: 'input-validation-error' }, style: { backgroundColor: prizeNum == 0 ? '#FFFCCE' : '#ffffff'}" class="form-control" /></div> 
      </td> 
      <td> 
       <div data-bind="if: ($index() === ($parent.items().length - 1))"><input data-bind="value: itemOrder, valueUpdate: 'afterkeydown', enterPress: 'addRow', attr: { name: 'brochureitems[' + $index() + '].itemOrder', id: 'brochureItems_' + $index() + '__itemOrder' }, validationOptions: { errorElementClass: 'input-validation-error' }, style: { backgroundColor: itemOrder == 0 ? '#FFFCCE' : '#ffffff'}" class="form-control" /></div> 
       <div data-bind="if: ($index() < ($parent.items().length - 1))"><input data-bind="value: itemOrder, valueUpdate: 'afterkeydown', attr: { name: 'brochureitems[' + $index() + '].itemOrder', id: 'brochureItems_' + $index() + '__itemOrder' }, validationOptions: { errorElementClass: 'input-validation-error' }, style: { backgroundColor: itemOrder == 0 ? '#FFFCCE' : '#ffffff'}" class="form-control" /></div> 
      </td> 
      <td class="remove"><span class="glyphicon glyphicon-remove removeRow" data-bind="click: $parent.removeItem"></span></td> 

     </tr> 
    </tbody> 
</table> 

Knockout:

ko.validation.rules.pattern.message = 'Invalid.'; 
ko.validation.init({ 
    registerExtenders: true, 
    messagesOnModified: true, 
    insertMessages: true, 
    parseInputAttributes: true, 
    messageTemplate: null, 
    decorateInputElement: true, 
}, true); 

(function(){ 

    var toMoney = function(num){ 
    if(num != null && num != "") { 
     num = parseFloat(num); 
     return (num.toFixed(2).replace(/(\d)(?=(\d{3})+\.)/g, '$1,')); 
    } else { 
     return ""; 
    } 
    }; 

    var handler = function(element, valueAccessor, allBindings){ 
    var $el = $(element); 
    var method; 

    // Gives us the real value if it is a computed observable or not 
    var valueUnwrapped = ko.unwrap(valueAccessor()); 

    if($el.is(':input')){ 
     method = 'val'; 
    } else { 
     method = 'text'; 
    } 
    return $el[method](toMoney(valueUnwrapped)); 
    }; 

    ko.bindingHandlers.money = { 
    update: handler 
    }; 
})(); 

var itemModel = function (data) { 
    var self = this; 
    self.invalidItem = ko.observable(true); 
    self.itemNo = ko.observable(data ? data.itemNo : undefined).extend({ 
    required: { 
     params: true, 
     message: "Item no. required." 
    } 
    }); 
    self.brocCode = ko.observable(data ? data.brocCode : undefined).extend({ 
    required: { 
     params: true, 
     message: "Bro code required." 
    } 
    }); 
    self.itemDesc = ko.observable(data ? data.itemDesc : undefined).extend({ 
    required: { 
     params: true, 
     message: "Item desc required." 
    } 
    }); 
    self.retail = ko.observable(data ? data.retail : undefined).extend({ 
    required: { 
     params: true, 
     message: "Retail required." 
    } 
    }) 
    .extend({numeric: 2}); 
    self.prizeNum = ko.observable(data ? data.prizeNum : undefined).extend({ 
    required: { 
     params: true, 
     message: "Prize num required." 
    } 
    }); 
    self.itemOrder = ko.observable(data ? data.itemOrder : undefined).extend({ 
    required: { 
     params: true, 
     message: "Item order required." 
    } 
    }); 
} 

var itemsModel = function(items) { 
    var self = this; 
    self.items = ko.mapping.fromJSON(items); 

    //self.invalidItem = ko.observable(true); 

    self.checkItemNo = function(data) { 
    console.log("lost focus - " + self.invalidItem()); 
    var itemNo = $.trim(data.itemNo()); 

    if (itemNo != "") { 
     var item = ""; 
     $.each(window.listOfItems, function(i, v) { 
     if (v.No.search(itemNo) != -1) { 
      item = v.Description; 
      return; 
     } 
     }); 
     if(item != "") { 
     var match = ko.utils.arrayFirst(self.items(), function(newItem) { 
      return itemNo === newItem.itemNo; 
     }); 
     console.log("match: " + match); 
     if (!match) { 
      data.itemDesc(item); 
     } else { // item already entered 
      //setTimeout(function() { self.items.invalidItem(true); }, 1); 
      data.itemDesc(""); 
      slideDownMsg("Item already entered."); 
      slideUpMsg(3000); 
     } 
     } else { // invalid item # 
     console.log(data); 
     data.invalidItem(true); 
     //setTimeout(function() { data.invalidItem(true); }, 1); 
     data.itemDesc(""); 
     slideDownMsg("Invalid item number."); 
     slideUpMsg(3000); 
     } 
    } 
    } 

    self.submit = function() { 
    //self.showErrors(true); 
    if (viewModel.errors().length === 0) { 
     console.log('Thank you.'); 
     $("#brochureForm").submit(); 
    } 
    else { 
     console.log('Please check your submission.'); 
     viewModel.errors.showAllMessages(); 
     $(".input-validation-error").first().focus(); 
    } 
    } 

    self.addLine = function() { 
    var iModel = new itemModel(); 
    iModel.invalidItem(true); 
    //self.invalidItem(true); 
    console.log("adding new line; it is: " + iModel.invalidItem()); 
    self.items.push(iModel); 
    //setTimeout(function() { self.invalidItem(true); }, 1); 
    }; 

    self.insertLine = function(index) { 
    self.items.splice(index, 0, new itemModel()); 
    }; 

    self.removeItem = function(item) { 
    self.items.remove(item); 
    }; 

    self.errors = ko.validation.group(self.items, { deep: true, live: true }); 

    self.validate = function() { 
    self.errors.showAllMessages(); 
    } 
}; 

ko.bindingHandlers.enterPress = { 
    init: function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) { 
    var allBindings = allBindingsAccessor(); 
    element.addEventListener('keydown', function (event) { 
     var keyCode = (event.which ? event.which : event.keyCode); 
     if (keyCode === 13 || (!event.shiftKey && keyCode === 9)) { 
     event.preventDefault(); 
     //bindingContext.$root.invalidItem(false); 
     bindingContext.$root.addLine(); 
     return false; 
     } 
     return true; 
    }); 
    } 
}; 

ko.bindingHandlers.insertPress = { 
    init: function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) { 
    var allBindings = allBindingsAccessor(); 
    element.addEventListener('keydown', function (event) { 
     var keyCode = (event.which ? event.which : event.keyCode); 
     if (keyCode === 45) { 
     event.preventDefault(); 
     bindingContext.$root.insertLine(ko.unwrap(valueAccessor())); 
     return false; 
     } 
     return true; 
    }); 
    } 
}; 

ko.bindingHandlers.selected = { 
    update: function(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) { 
    var selected = ko.utils.unwrapObservable(valueAccessor()); 
    if (selected) element.select(); 
    } 
};   

    function GetItems() { 
    var itemsJSON = '[{"brochureId":1,"itemNo":"1000","brocCode":"1000","itemDesc":"Bicycle","retail":13.5, "prizeNum":1, "itemOrder":1},{"brochureId":1,"itemNo":"1100","brocCode":"1100","itemDesc":"Front Wheel","retail":35, "prizeNum":2, "itemOrder":2},{"brochureId":1,"itemNo":"1120","brocCode":"1120","itemDesc":"Spokes","retail":12.5, "prizeNum":3, "itemOrder":3},{"brochureId":1,"itemNo":"1150","brocCode":"1150","itemDesc":"Front Hub","retail":5, "prizeNum":4, "itemOrder":4},{"brochureId":1,"itemNo":"1151","brocCode":"1151","itemDesc":"Axle Front Wheel","retail":14, "prizeNum":5, "itemOrder":5},{"brochureId":1,"itemNo":"120","brocCode":"120","itemDesc":"Loudspeaker, Black, 120W","retail":12.5, "prizeNum":6, "itemOrder":6},{"brochureId":1,"itemNo":"125","brocCode":"125","itemDesc":"Socket Back","retail":10, "prizeNum":7, "itemOrder":7}]'; 
    var viewModel = new itemsModel(itemsJSON); 
    ko.applyBindings(viewModel, $("#brochureItems")[0]); 
    } 

$(document).ready(function() { 
    GetItems(); 
}); 

Antwort

2

Es sagt itemNo nicht definiert ist, weil Sie itemNo zu undefinierten setzen, wenn keine Daten in übergeben wurde:

self.itemNo = ko.observable(data ? data.itemNo : undefined)...

Sie können

self.itemNo = ko.observable(data ? data.itemNo : '').extend({ 
    required: { 
     params: true, 
     message: "Item no. required." 
    } 
}); 
+0

Aw, danke ein Haufen! – dmikester1