1

고객 주문 및 많은 주문 항목을 모델링하는 KnockoutJS 뷰 모델을 만들려고합니다. 초기 데이터를로드하고 데이터의 유효성을 검사하려고합니다.관찰 가능한 배열을 사용한 Knockoutjs 매핑 및 유효화

지금까지 knockoutjs.mapping을 사용하여 데이터를로드 할 수 있었지만 매핑을 사용하여 추가 된 데이터의 유효성을 검사했습니다.

// data to load into viewmodel 
var modeldata = { 
    "OrderID":1, 
    "ReturnString":null, 
    "CustomerName":"First Customer", 
    "OrderDate":"2013-09-16T19:41:40.1639709+01:00", 
    "OrderItems": [ 
    {"ItemID":0, 
     "ItemName":"Name_0", 
     "ItemPrice":0.0, 
     "_destroy":false 
    }, 
    {"ItemID":1, 
     "ItemName":"Name_1", 
     "ItemPrice":10.0, 
     "_destroy":false 
    }, 
    {"ItemID":2, 
     "ItemName":"Name_2", 
     "ItemPrice":20.0, 
     "_destroy":false 
    } 
    ] 
}; 


// setup defaults for validation 
var validationOptions = { 
    insertMessages: true, 
    decorateElement: true, 
    errorElementClass: 'errorCSS', 
    messagesOnModified: true, 
    debug: true, 
    grouping: { 
     deep: true, 
     observable: false //Needed so added objects AFTER the initial setup get included 
    }, 
}; 

ko.validation.init(validationOptions); 


// define array model 
var Item = function() { 
    var self = this; 
    ItemID = ko.observable(); 
    ItemName = ko.observable().extend({ 
     required: { message: '* item name needed' } 
    }); 
    ItemPrice = ko.observable(); 
    _destroy = false; 
} 

// define view model 
var ViewModel = function (data) { 
    var self = this; 
    self.OrderID = ko.observable(); 
    self.ReturnString = ko.observable(); 
    self.CustomerName = ko.observable().extend({ 
     required: { message: '* customer name needed' } 
    }); 
    self.OrderDate = ko.observable(); 
    self.OrderItems = ko.observableArray([]); // to be array of "Item" 

    // create validation group 
    self.orderErrors = ko.validation.group(self); 
    self.orderItemErrors = ko.validation.group(
     self.OrderItems, { deep: true } 
    ); 

    self.lineItemsValid = function() { 
     var LValid = false; 
     if (self.orderItemErrors().length > 0) { 
      if (self.orderItemErrors()[0] != null) // important to test for null 
       LValid = false; 
      else 
       LValid = true; 
      } 
     else LValid = true 
     if (LValid) { 
      return true 
      } 
     else 
      { 
      self.orderItemErrors.showAllMessages(); 
      return false; 
      } 
    } 

    self.orderValid = function() { 
     var LValid = false; 
     if (self.orderErrors().length > 0) { 
      if (self.orderErrors()[0] != null) // important to test for null 
       LValid = false; 
      else 
       LValid = true; 
     } 
     else LValid = true 
     if (LValid) { 
      return true 
     } 
     else { 
      self.orderErrors.showAllMessages(); 
      return false; 
     } 
    } 

    self.isValid = function() { 
     if(self.orderValid() & self.lineItemsValid()){ 
     alert('All ok!') 
     } 
     else{ 
     alert('Errors!');} 
    } 


    // operations 
    self.addLineItem = function() { 
     self.OrderItems.unshift(new Item()); 
    } 

    self.removeLineItem = function (item) { 
     self.OrderItems.destroy(item); 
    } 

    // load data into model 
    self.loadData = function() { 
     ko.mapping.fromJS(modeldata, {}, self); 
    } 


} 

$(document).ready(function() { 
    var viewModel = new ViewModel() 
    ko.applyBindings(viewModel); 
}); 

문제 :

(1) 나는 또한 클릭 기능을 사용하여 주문 항목, 그러나이의 데이터가 관측 배열에 업데이 트하지 않는 것을 추가 할 수 있습니다. 그러나 "항목 제거"함수를 호출하면 배열 항목이 삭제됨으로 표시됩니다.

(2)가 매핑 항목을로드하고, 확인을 테스트 할 때, 그것은 지도를 통해로드 된 항목 내가 매핑 후 추가하지 주문 - 항목 만이 완료 작업 (= TRUE 필수)

(3) 매핑으로 가져온 주문 항목을 업데이트하면 변경 사항이 관찰 가능한 배열에 즉시 반영됩니다. 매핑 후에 추가 한 주문 항목을 업데이트하면 배열에 업데이트가 없습니다.

내가 여기 JSFiddle 있습니다

http://jsfiddle.net/devops/ZsDjh/40/

나는 내가 관찰 배열에 추가하고 어떻게 함께 할 수있는 뭔가하지만 분명 아무것도 볼 수 없습니다 확신 - 나는 분명히 기본적인 뭔가를 놓친 거지 .. 누구든지 아이디어가 있다면?

감사합니다.

답변

8

사소한 간과 만 있습니다.

먼저,로 이동하자 (3)

(3) 내가 매핑에 의해 가져온 주문 항목을 업데이트 할 때, 변화는 내가 주문 항목을 업데이트 관찰 배열에 즉시 반영됩니다 매핑 후에 추가 한 배열에 업데이트가 없습니다.

Item 함수에서 속성은 (자체)에 바인딩되어야합니다.

(2) 지금
var Item = function() { 
    var self = this; 
    self._destroy = false; 
    self.ItemID = ko.observable(); 
    self.ItemName = ko.observable().extend({ required: { message: '* item name needed' } }); 
    self.ItemPrice = ko.observable(); 
} 

,

내가 매핑 항목을로드하고, 확인을 테스트 할 때 (2) (= TRUE 필수),이지도를 통해로드 된 항목에 대해서만 작동, 맵핑이 완료된 후에 추가 한 주. 항목이 아님

이는 맵핑 플러그인을 사용하는 f}과 OrderItems observableArray에 새 항목을 추가하는 f}에 기인합니다.

// load data into model 
self.loadData = function() { 
    ko.mapping.fromJS(modeldata, {}, self); 
} 

나는 당신의 바이올린에서 이것을 복제 할 수 없지만, 나는 일어날 가능성이 매우 높습니다.

는 매핑 pluging는 단순히 배열의 객체는 각 OrderItems에이 새가 될 수 있음을 모르고있다하여 JSON에서 관찰 할 수있는 속성을 생성하고 각각 할당 (또는 경우에 재 할당) 자기에 등록되어 있기 때문에 항목() 개체입니다. 익명의 관찰 가능한 객체를 생성하고이를 새로운 observableArray에 배치 한 다음이를 self.OrderItems에 할당합니다.

매핑을 처리하는 방법을 지시해야합니다.

// outside your viewmodel 
var itemMapping = { 
    create: function (options) { 
     return new Item(options.data); 
    } 
}; 

// load data into model 
self.loadData = function() { 
    ko.mapping.fromJS(modeldata, { OrderItems: itemMapping }, self); 
} 

이제 우리는 itemMapping만들 기능에 JSON 배열의 각 항목을 통과하고 있습니다. 그러나 이제는 문제가 있습니다. Item 함수는 매개 변수를 사용하지 않습니다. 그래서 고칠 수 있습니다. 그리고 그것에 머무는 동안 매퍼가 항목에 대해 관찰 가능한 속성을 생성하는 데 다시 도움을 주도록 할 수 있습니다. 우리는 당신의 품목의 기능을 수정 한 이후

var Item = function (data) { 
    var self = this; 
    self._destroy = false; 
    //self.ItemID = ko.observable(data.ItemID); 
    //self.ItemName = ko.observable(data.ItemName).extend({ required: true }); 
    //self.ItemPrice = ko.observable(data.ItemPrice); 
    ko.mapping.fromJS(data, {}, self); 
    self.ItemName.extend({ required: { message: '* item name needed' } }); 
} 

우리는 addLineItem 방법을 업데이트해야합니다. 이제

// operations 
self.addLineItem = function() { 
    // set the default values 
    self.OrderItems.unshift(new Item({ ItemId: null, ItemName: "", ItemPrice: 0 })); 
} 

, 을 self.lineItemsValid 및 방법을 self.orderValid하고 self.orderItemErrors에게 속성을 제거하여 제거.

isValid 메서드의 이름을 변경하고 업데이트하십시오.

self.checkValid = function() { 
    if(self.isValid()){ 
     alert('All ok!'); 
    } 
    else{ 
     self.orderErrors.showAllMessages(); 
    } 
} 

self.isValid()는는 검증 플러그인에 의해 생성하는 방법이다. 당신은 그것을 덮어 썼습니다.

그리고 html을 업데이트하십시오. 마지막으로

<a href="#" data-bind="click: checkValid">Check is valid</a> 

(1),

(1) 나는 또한 클릭 기능을 사용하여 주문 항목을 추가 할 수 있지만, 이들의 데이터가 관측 배열에 업데이 트하지 않는 것 .

함수에 대한 수정 사항으로 수정되었습니다.

그러나 "항목 제거"기능을 호출하면 배열 항목이 삭제됨으로 표시됩니다.

나는 당신이 그것을 제거 완료 또는 을 _destroyed로 간단하게 표시 할 것인지 확실하지 않다.

제거하려는 경우 removeLineItem 메소드를 업데이트하십시오.

self.removeLineItem = function (item) { 
    self.OrderItems.remove(item); 
} 

Observable Arrays에 녹아웃 설명서를 참조하고 제거에 대해 읽고 가장 적합한에게 무엇을 결정하는 방법을 파괴하십시오.

여기는 modified jsFiddle입니다.

건배!

P. 이 답변이 당신의 바퀴에 기름을 바르기 때문에 +1하십시오! :)

+0

안녕하세요 로저 - 정말 고마워요, 바퀴가 기름을! ... 대단히 감사합니다. – qtime67