2013-03-20 2 views
0

JSON 호출에서 채워지는 녹아웃 뷰 모델이 있습니다. 양식의 select 요소에는 viewmodel에서 오는 옵션 집합과 observableArray 부분의 값이 있습니다. 문제는 select 요소에만 있고 입력 요소에는 문제가 없습니다. 양식을 제출할 때 select에 할당 된 값만 적절한 값을 포함합니다. 따라서 JSON에서 성공적으로로드되어 양식으로 제공되었지만 변경되지 않은 옵션은 options 배열의 첫 번째 값으로 서버에 다시 전송됩니다.knockout.js select 요소 바인딩이 후속 양식 제출시 값을 잃습니다.

HTML 양식 : 문제 위의 코드에서

<form> 
    <table > 
     <thead> 
      ... 
     </thead> 
     <tbody data-bind='foreach: ScaledCostEntries'> 
      <tr> 
       <td><input data-bind='value: StartDateString' class="startdate" type="text"/></td> 
       <td><select data-bind='value: InvoiceType, options: $root.InvoiceTypes'></select></td>      
       <td><a href='#' data-bind='click: $root.removeCost'>Delete</a></td> 
      </tr> 
     </tbody> 

    </table> 
    <button data-bind='click: addCost'>Add New Row</button> 
    <button data-bind='click: save' >Update</button> 
</form> 

는 viewmodels ScaledCostEntries observableArray의 InvoiceType, 부분입니다. (또한, 만약 내가 값과 옵션의 순서를 바꾸면 select 요소에 선택된 값을 넣지 않을 것이다).

과 JS

:

그래서
<script type="text/javascript"> 
    $(function() { 
     var scaledCostModel = function() { 
      var self = this; 

      self.ScaledCostEntries = ko.observableArray([]); 
      self.InvoiceTypes = ko.observableArray([]); 

      self.addCost = function() { 
       self.ScaledCostEntries.push({      
        StartDateString: ko.observable(), 
        InvoiceType: ko.observable() 
       }); 
      }; 

      self.removeCost = function (cost) { 
       cost.IsDeleted = true; 
       self.ScaledCostEntries.destroy(cost); 
      }; 

      self.save = function (form) { 
       jQuery.ajax({ 
        url: '@Request.Url.PathAndQuery', 
        type: "POST", 
        dataType: "json", 
        contentType: "application/json; charset=utf-8", 
        data: ko.toJSON(self.ScaledCostEntries)      
       }); 
      }; 
     }; 

     jQuery.getJSON('@Request.Url.PathAndQuery', function (data) { 
      ko.mapping.fromJS(data, {}, viewModel); 
     }); 

     var viewModel = new scaledCostModel(); 

     ko.applyBindings(viewModel); 
    }); 
</script> 

은, 요약하기는 문제는 선택 요소에 바인드 뷰 모델의 속성입니다. 선택 항목을 변경하지 않으면 (다시 선택하지 않음) 서버에 게시 할 때 viewmodel은 옵션 (InvoiceTypes) 배열의 첫 번째 항목으로 값을 갖습니다. 결국, 나는 사소한 것을 잊어 버렸을 것이고 이것은 나의 첫번째 더 심각한 녹아웃이다. 시도.

참고 : InvoiceTypeScaledCostEntries의 일부이며 observableArray입니다. InvoiceTypesobservableArray입니다. InvoiceTypesScaledCostEntries은 모두 JSON에서 가져온 것이므로 ScaledCostEntries이 다시 전송됩니다.

+0

ajax 호출의 시작 부분에 크롬이나 다른 브라우저 디버거에 중단을 넣고 self.ScalsedCostEntries 배열에있는 내용을 볼 수 있습니까? – zmanc

+0

@zmanc : 네, 해냈습니다. 값을 다시 선택하면 가치가 있습니다. 다른 행의 값을 형성하거나 다시 선택하지 않은 경우 편집되지 않은 항목에는 선택 옵션 인 InvoiceTypes [0]의 첫 번째 요소가 포함됩니다. –

답변

3

내 가정은 양식 제출시 서버에서 ScaledCostEntries이 처리되는 방식 때문입니다.

주 모델에 추가 및 제거되는 종속 모델 목록이있는 경우 (여러 서버 측 프레임 워크에서) 문제가 발생하여 주 모델에 대해 양식 제출이 완료되었습니다. 모든 것을 업데이트하십시오.

문제는 양식 제출 중에 요청의 값이 서버 측 모델에 매핑 될 때 공백 값이 "삭제하지 않음"이 아니라 "변경하지 않음"을 의미한다는 것입니다. 이는 모델의 특성과 직접적으로 잘 작동하지만 종속 모델 목록에는 적용되지 않습니다.

Ajax를 사용하여 기본 모델을 삭제하고보기에서 '제거'또는 '삭제'버튼을 누르면 기본 모델과의 관계를 업데이트 할 수 있습니다. 매번 모델의 전체 목록을 명시 적으로 보내고 양식 제출마다 서버에서 목록을 명시 적으로 삭제하고 다시 작성하십시오. 각각은 다른 상황에 적용 할 수 있으며 잘 작동하는 다른 접근법이있을 수 있습니다.

+0

답장을 보내 주셔서 감사합니다. @Nate.이것은 나에게 생각이 떠올랐다. 그래서 첫 번째 옵션 배열에 여분의 (빈) 값을 추가하여 문제를 해결했다. 따라서 값을 편집하지 않고 서버에 다시 보낼 때마다 그 값을 포함하게된다. 대신 빈 값을 사용하면 서버 측에서 처리 할 수 ​​있습니다. –

+0

그러나 여전히 select 요소의 기발한 동작을 해결하거나 설명하지는 않습니다. –

+0

'@ Request.Url.PathAndQuery'에서 JSON의 예를 게시 할 수 있습니까? 내가 생각할 수있는 유일한 방법은 InvoiceTypes의 옵션 목록과 일치하지 않는 ScaledCostEntries.InvoiceType 필드의 값일 것입니다. 그런 다음보기에서 해당 항목에 설정된 첫 번째 값을 확인해야합니다. – Nate