1

MVC 프로젝트에서 녹아웃 (KO)을 사용하고 있습니다. 서버에 MVC 모델 (그리드 용)을 만들어 뷰에 전달합니다. 뷰에서는 직렬화되고 바인딩에 사용되는 KO 모델 (ko.mapping 사용)으로 변환됩니다. 그 바인딩은 그리드 생성을 위해 HTML에서 사용됩니다.관찰 가능한 배열의 녹아웃 매핑이 작동하지 않는 것 같습니다.

이것은 ko.mapping에 의해 내 MVC 그리드 모델이되는 것처럼 다시 해당 KO 모델로 변환됩니다 모습입니다 :

public class GridModel 
    { 
     /// <summary> 
     /// Grid body for the grid. 
     /// </summary> 
     public GridBodyModel GridBodyModel { get; set; } 

     /// <summary> 
     /// Grid context. 
     /// </summary> 
     public GridContext GridContext { get; set; } 

     /// <summary> 
     /// Grid header for the grid. 
     /// </summary> 
     public GridHeaderModel GridHeader { get; set; } 
    } 

public class GridBodyModel 
    { 
     /// <summary> 
     /// List of grid body rows. 
     /// </summary> 
     public IList<GridRowModel> Rows { get; set; } 
    } 


public class GridContext 
    { 
     /// <summary> 
     /// Total number of pages. Read-only. 
     /// </summary> 
     public int TotalPages{ get; set; } 
    } 

public class GridHeaderModel 
    { 
     /// <summary> 
     /// List of grid header cells. 
     /// </summary> 
     public IList<GridHeaderCellModel> Cells { get; set; } 
    } 

가 메인 모델 클래스 GridModel가있는 다음과 같은 클래스 구성되어 알 수있는 바와 같이

GridBodyModel : 그리드 본문에 렌더링 할 행 목록이 있습니다.

GridContext : 총 페이지 수가 속성으로 있습니다. 다른 속성도 있지만이 내용은이 토론의 범위를 벗어납니다.

GridHeaderModel : 표 머리글에 표시되어야하는 셀 목록이 있습니다.

그런 다음이 스크립트를 새로운 페이지로드시 실행할 것입니다.

$(document).ready(function() { 
     // Apply Knockout view model bindings when document is in ready state. 
     ko.applyBindings(Global_GridKOModel, document.getElementById("gridMainContainer")); 
    }); 

// Serialize the server model object. It will be used to create observable model. 
Global_GridKOModel = ko.mapping.fromJS (<%= DataFormatter.SerializeToJson(Model) %>); 

Global_GridKOModel는 글로벌 자바 스크립트 변수입니다. 모델은 서버에서 오는 MVC 모눈 모델입니다.

사용자가 페이지에서 추가 검색을 다시 수행 할 수 있습니다. 나는 Ajax를 통해 새로운 검색 기준을 게시하여이를 처리한다. 이 게시물에서 새로운 MVC 모델이 생성되고 Ajax 응답으로 다시 전송됩니다. 이 새로운 MVC 모델은 ko.mapping을 사용하여 Global_GridKOModel을 업데이트하는 데 사용됩니다. ko.mapping은 새 페이지로드에서 이전에 생성 된 그리드 (새 데이터 포함)를 새로 고칩니다. 이것이 내가하는 방식이다.

$.ajax({ 
     url: destUrl, 
     data: dataToSend 
     success: function (result) { 
      ko.mapping.fromJS(result, Global_GridKOModel); 
     }, 
     error: function (request, textStatus, errorThrown) { 
      alert(request.statusText); 
     } 
    }); 

다음 시나리오를 제외하고 모든 것이 잘 작동합니다.

모델 GridModel에서 GridBodyModel이고 GridHeaderModel이 null 인 Ajax 요청이 반환됩니다. 그 시간표는 기록이 발견되지 않았 음을 보여줍니다. 이 말이 맞습니다. 이것은 다음 HTML 바인딩에서 발생합니다.

<!-- When no record is found. --> 
<div data-bind="ifnot: GridContext.GridPager.TotalPages() > 0"> 
    No record(s) were found. 
</div> 

<!-- This is actual grid table container. This is binded when records are found --> 
<div data-bind="if: GridContext.TotalPages() > 0"> 

Grid construction happens here 

</div> 

이제 한 후이 다른 Ajax 요청이 이루어진다하지만 레코드가 반환되는이 시간이 (내가 불을 지르고와 응답을 확인하고 그 기록은 참으로 반환됩니다 확인)합니다. 이 시간 격자 구성은 다양한 관측 가능한 배열이 액세스되는 곳에서 발생합니다. 예를 들어, 그리드에 대한 호출기를 구성하려면 다음과 같이 HTML 바인딩을 사용합니다.

<td data-bind="attr:{colspan: GridHeader.Cells().length }"> 

KO가 불을 지르고에서 볼 수있는 오류 다음 발생이 시간.

바인딩을 구문 분석 할 수 없습니다. 메시지 : TypeError : GridHeader.Cells는 함수가 아닙니다. 바인딩 값 : ATTR {열 병합 :. GridHeader.Cells() 길이}

그것은 잘 작동 너무 오래 반환되는 레코드가 있지만 위에서 설명한대로 더 레코드가 반환되지 않으면이 나옵니다.레코드가 반환되지 않은 경우 GridHeader는 이전 응답에서 null이었습니다. 나는 ko.mapping에서 뭔가 비린내가 난다. 내가 관찰 가능한 배열을 매핑하는 동안 몇 가지 문제가 있다고 생각합니다.

그럼 내가 옳지 않은 것은 무엇입니까? 누구든지 제발?

내가 명확하게 언급하지 않은 경우 명확하게 요청하십시오.

미리 감사드립니다.

답변

2

실제 동작 이유는 원래 GridHeader가 javascript 개체이지만 GridHeader 속성에 대해 null로 반환 전화 매핑을하면 null 값으로 관찰 가능 해지고 이후의 모든 업데이트에서 관찰 가능 상태가 유지됩니다.

해결 방법은 (하나를 선택)입니다 : - 나는 그것이 방법을

  • 또는 바람직하다 생각 -

    1. (대신 빈 개체를 반환) 자식 모델에 null 값을 반환하지 않는지도를 호출하기 전에, 을 실행 Global_GridKOModel .GridHeader = null; (업데이트 후 GridHeader가 관찰 가능하지 않음을 보장)
    2. 또는 매핑 후 을 호출하십시오. Global_GridKOModel.GridHeader = ko.unwrapObservable (Global_GridKOModel.GridHeader);
    당신이 행동의

    전체 설명 (jsfiddle에 복사 - http://jsfiddle.net/nickolsky/zrBuL/9/) 아래의 코드에이 매핑 플러그인의 설계 문제처럼 보이는 나를 위해

    console.log('step1'); 
    var vm = ko.mapping.fromJS({ body: { children: [ 1, 2, 3]} }); 
    console.log(vm.body.children()[1]); //prints 2 
    
    console.log('step2'); 
    ko.mapping.fromJS({ body: { children: [ 4, 5, 6]} }, vm); 
    console.log(vm.body.children()[1]); //prints 5 
    
    console.log('step3'); 
    //after next call, vm.body is no longer variable - it is now observable 
    ko.mapping.fromJS({ body: null }, vm); 
    console.log(vm.body); //prints observable 
    console.log(vm.body()); //prints null 
    
    console.log('step4'); 
    //and it will remain observable for next call 
    ko.mapping.fromJS({ body: { children: [ 7, 8, 9]} }, vm); 
    console.log(vm.body().children()[1]); //prints 8 
    console.log(vm.body().children().length); //prints 3 
    console.log(vm.body); //prints observable function body 
    console.log(vm.body()); //prints object 
    
    //workaround for null issue - we can reset it to be null instead of null observable 
    //and it will get original behavior 
    vm.body = null; 
    console.log('step5');  
    ko.mapping.fromJS({ body: { children: [ 7, 8, 9]} }, vm); 
    console.log(vm.body.children()[1]); //prints 8 - body is no longer observable again 
    ​ 
    

    , 내가 할 수있는 방법을 찾을 수 없습니다 하위 viewmodel 속성에 대한 매핑을 맞춤화하여 null 인 경우 관찰 가능하게되지 않도록하십시오 ('복사'기능을 사용하면 모든 내부 콘텐츠를 관찰 할 수없는 것으로 유감스럽게 볼 수 있습니다).

  • +0

    Artem을 읽어 주셔서 감사합니다. 네 말이 맞습니다. null은 반환되어서는 안됩니다. 나는 지난 밤에 그것을 알아 냈다. 그러나 게시하지 않았다. 아래에 제 대답을 읽으십시오. 제 관찰을 언급 한 부분과 당신이 말한 것을 정확히 반영합니다. – Aum

    1

    어젯밤에 알아 냈습니다. 사실 이것은 내가 작성한 아주 기본적인 실수였습니다. null로 설정 한 후 배열에 액세스하려고했습니다. 나는 그것을 어떻게 설명 할 것이다.

    그 결과 GridHeaderModel 및 그 안에있는 IList 셀이 정의되었거나 null이 아닌 경우 결과가 반환되었습니다. 그 때 ko.mapping은 모델을 변환하고 모델을 만들었으며 내부에서는 오정렬했습니다. 그러나 noo 결과가 반환되고 GridHeaderModel이 null 인 아약스 요청이있을 때 분명 IList 셀도 null입니다. ko.mapping도 KO 모델을 업데이트했고, GridHeaderModel을 null로 설정했으며, 관찰 가능한 배열 Cells 내부는 null이 아니 었습니다. 이제 일부 레코드가 반환 된 다른 아약스 요청을했을 때 ko.mapping은 클라이언트의 KO 모델에서 존재하지 않았거나 null로 설정된 관찰 가능 어레이 Cell을 업데이트하려고 시도했지만 실패했습니다. 아약스 대신에 새로운 페이지로드가 있다면 모든 것이 효과적이었을 것입니다. 따라서 솔루션은 KO 모델 업데이트를 위해 클라이언트에 초기화되지 않은 열거 형 (관찰 가능한 배열로 변환 될 열거 형)을 반환하지 않아야합니다. 따라서 레코드가 반환되지 않을 때 GridHeaderModel이 null이 아니며 IList Cells가 초기화되지 않았는지 확인했습니다. IList Cell은 요소를 포함하지 않았지만 초기화되었습니다. 이 문제가 해결되었습니다.

    이 문제는 다음 예제와 함께 설명 할 수 있습니다. 여기에 우리는 클래스 인스턴스 데모하지만 IList의 DemoArray를 초기화 한 UseDemo() 메소드에

    public class Demo 
    { 
        public IList<string> DemoArray; 
    } 
    
    public class DemoUser 
    { 
        public void UseDemo() 
         { 
          var demoInstance = new Demo(); 
          demoInstance.DemoArray.Add("First Element"); 
         } 
    } 
    

    는 초기화되지 않은 남아있다. 그래서 우리가 접근하려고 할 때 런타임 예외가 던져 질 것입니다. 이것은 내 경우에서 일어난 일입니다.첫 번째 아약스 응답에서 관찰 가능 배열을 null로 설정했습니다. 즉 초기화하지 않은 상태에서 다음 아약스 응답에 액세스하려고했습니다.