2014-09-26 2 views
0

IEnumerable 형식의 모델을 JS 문자열로 변환하고 숨겨진 입력에 저장하는 ASP.NET MVC 프로젝트가 있습니다. 그런 다음 요소의 data-bind = "foreach : rows"가 바인딩되는 viewModel 객체에 applyBindings 시간에 해당 문자열을 구문 분석합니다. 이 시스템은 내가 일하고 쉽게 재사용 가능한 시스템으로 구축해야하는 곳에서 내부적으로 개발 된 MVC 프레임 워크의 일부입니다. 가장 중요한 디자인 목표는 레이아웃을 유도하는 속성으로 .NET ViewModel을 작성하기 위해 코드를 소비하는 것입니다. 개발자가 일치하도록 JS보기 모델을 작성하지 못하게하려고합니다.녹아웃 JS 더티 플래그 만들기

var thingy = function(rowData){ 
    rows = ko.mapping.fromJS(rowData); 
}; 


var el1 = $("#someGrid > tbody"); 
if (el1.length > 0) { 
    var dataStr = el1.attr("data-ko-data"); 
    var data = JSON.parse(dataStr); 
    var vm = thingy(data); 

    ko.applyBindings(vm, el1[0]); 

} 

내 .NET POCO는 다음과 같습니다 :

JS 나는 다음과 같이 바인딩은 초기화하기위한 샘플 프로젝트에이 형태의 각 테이블이있다

public class Person 
{ 
    public int Id { get; set; } 
    public string FirstName { get; set; } 
    public string Surname { get; set; } 
    public int Age { get; set; } 
    public bool IsDirty { get; set; } 

    public Tuple<string, Type>[] Properties() 
    { 
     var propInfos = this.GetType().GetProperties(); 
     var ret = propInfos.Select(i => new Tuple<string, Type>(i.Name, i.PropertyType)); 
     return ret.ToArray(); 

    } 
} 

" 테이블의 viewmodel을 스캔하고 IsDirty = true로 표시된 행을 MVC Action에 저장하여 저장하십시오.

$(".gridSaveButton").click(function() { 
    var theUrl = $(this).attr("data-saveurl"); 
    var theTable = $(this).siblings("table"); 

    var dirtyRows = []; 

    var theBody = theTable.children("tbody"); 
    var trs = theBody.children("tr"); 
    trs.each(function() { 
     var row = $(this); 
     var modelForRow = ko.dataFor(row[0]); 
     if(modelForRow.IsDirty) 
     { 
      dirtyRows.push(modelForRow); 
     } 

    }); 

    var theData = ko.toJSON(dirtyRows); 
    $.ajax({ 
     url: theUrl, 
     type: "POST", 
     contentType: "application/json", 
     data: theData, 
     success: function (status) { 
      alert("Success: " + status.Success); 
     }, 
     error: function (request, status, theError) { 
      alert(theError); 
     } 
    }); 

}); 

따라서 위의 예상대로 작동합니다. 문제가있는 것은 개체의 속성 중 하나가 수정 될 때 IsDirty 값을 특정 행에 대해 true로 설정하는 방법입니다. 지금까지 선상에서 발견 한 모든 예제는 IsDirty를 특정 다른 ko.observables를 기반으로 ko.computed로 설정하는 것을 다루지 만 사용자가 각 유형에 대해 명시적인 JS 뷰 모델을 작성해야하기 때문에 직접 수행 할 수는 없습니다 .

사용자 정의 바인딩을 만들려고했으나 init 또는 update 중 어느 쪽도 호출되지 않았으므로 약간 분실했습니다.

누구나 이런 종류의 경험이 있었고 객체의 선언이 내재적 일 때 객체의 다른 변수에 어떻게 간단하게 응답 할 수 있는지 알고 있었습니까?

- 스티브

+0

아마도 당신이하려고하는 것에 대해 과도한 것이지만, [breezejs] (http://www.breezejs.com/)를 살펴볼 것을 제안합니다. ASP Net 웹 API와 Entity Framework 또는 nhibernate와 함께 사용하면 개체의 더티 상태를 추적하고 서버의 모델에서 모델 클라이언트 측을 만들 수 있습니다. –

+2

또한 [스마트 IsDirty 깃발 만들기에 대한 블로그 게시물] (http://www.knockmeout.net/2011/05/creating-smart-dirty-flag-in-knockoutjs.html)도 도움이 될 수 있습니다. –

+2

가능한 [중복 플래그 기능을 만드는 방법] (http://stackoverflow.com/questions/14567269/how-to-create-dirty-flag-functionality) – Tanner

답변

0

좋아, 그래서 기본이 샘플을 사용하고 멋지게 일하고 있어요. 내가 ko.mapping.fromJS을 사용하고 내 요구에 맞게 수정 된 버전입니다 http://jsfiddle.net/rniemeyer/7Nsuh/

, 라이언의 원래 versionhttp에서 비록 : //jsfiddle.net/rniemeyer/dtpfv/ 뷰 모델에 dirtyItems 목록이있다. 수정 된 접근 방식을 사용하면 계산 된 dirtyItem을 koRowMapping에 추가하는 방법을 알 수 있습니까?

나는이 시도하지만 바인딩이 실패하고 접근 어쨌든 맞다면 난 잘 모르겠어요 :

var koRowMapping = { 
    rows: { 
     create: function (options) { 
      return createRow(options.data); 
     } 
    }, 
    dirtyItems: ko.computed(function() { 
     return ko.utils.arrayFilter(this.rows, function(row) { 
      return row.dirtyFlag.isDirty(); 
     }); 
    }, this) 
}; 
0

Roighto!

나는 결국 거기에 도착했다.

var koRowMapping = { 
    rows: { 
     create: function (options) { 
      return createRow(options.data); 
     } 
    } 

}; 

var createRow = function (row) { 
    var result = ko.mapping.fromJS(row); 
    result.dirtyFlag = ko.dirtyFlag(result); 
    return result; 
} 

ko.dirtyFlag = function (root, isInitiallyDirty) { 
    var result = function() { }, 
     _initialState = ko.observable(ko.toJSON(root)), 
     _isInitiallyDirty = ko.observable(isInitiallyDirty); 

    result.isDirty = ko.computed(function() { 
     return _isInitiallyDirty() || _initialState() !== ko.toJSON(root); 
    }); 

    result.reset = function() { 
     _initialState(ko.toJSON(root)); 
     _isInitiallyDirty(false); 
    }; 

    return result; 
}; 

그리고 다음 뷰 모델에 dirtyItems 글로벌 더러운 플래그를 넣어 :

그래서 그냥 라이언에 의해 원래의 예에 따라입니다

$(document).ready(function() { 
    var people = '{"rows":[{"FirstName":"Steve","LastName":"O"},{"FirstName":"Someone","LastName":"Else"}]}'; 

    var vm = ko.mapping.fromJSON(people, koRowMapping, {}); 
    vm.dirtyItems = ko.computed(function() { 
     return ko.utils.arrayFilter(this.rows(), function(item) { 
      return item.dirtyFlag.isDirty(); 
     }); 
    }, vm); 

    vm.isDirty = ko.computed(function() { 
     return this.dirtyItems().length > 0; 
    }, vm); 


    var el = $("#theTable"); 
    ko.applyBindings(vm, el[0]); 
} 

멋진 !!!!