2012-02-22 2 views
0

선택 목록이 올바른 옵션을 선택하여 렌더링되지 않습니다. 필자는 선택된 관측 값 (this.selected = ko.computed (parseInt (selected(), 10) == this.id;)을 계산하고 배열 함수에서 찾기 등 여러 가지 방법으로 시도했습니다.편집 모드로 전환 할 때 원래의 값을 어떻게 선택합니까?

프로덕션 환경에서 dataArea 요소는 서버 측 데이터로 채워집니다. div를 "data-"속성과 함께 사용하면 서버 측과 클라이언트 측 스크립팅이 분리되어 있습니다 (디자이너에게 도움이됩니다).

편집 버튼을 클릭하여 편집 할 옵션이있는 레코드가 먼저 비 편집 모드로 표시됩니다. 편집 모드에서는 레코드의 초기 값이 입력 컨트롤에 나타납니다. 다른 고객을 선택하고 양식에 새 연관된 프로젝트를로드하도록하는 옵션이 있습니다. 새 고객을로드하면 예상대로 프로젝트 목록이 재설정됩니다.

새로운 고객을로드하는 중에 문제가 발생하는 현재 값을 편집하는 것으로 전환하는 동안 문제가 발생합니다. 선택한 프로젝트가 드롭 다운 목록에 나타나야합니다. 새로운 고객이 선택되면 목록에는 새 옵션이 채워지고 기본값은 필요하지 않습니다.

http://jsfiddle.net/mathewvance/ZQLRx/

* 원래 샘플 http://jsfiddle.net/mathewvance/wAGzh/ *

감사 (무시하십시오).

<p> 
    issue: When the select options are read, the inital value gets reset to the first object in the options. How do I keep the original value selected when transitioning to edit mode? 
</p> 

<div> 
    <h2>Edit Quote '1001'</h2> 

    <div class="editor-row" data-bind="with: selectedCustomer"> 
     <label>Customer</label> 
     <div data-bind="visible: !$root.isEditMode()"> 
      <span data-bind="text: CompanyName"></span> 
     </div> 
     <div data-bind="visible: $root.isEditMode()"> 
      <input type="radio" name="customerGroup" value="1" data-bind="value: id"> Company Name 1 
      <input type="radio" name="customerGroup" value="2" data-bind="value: id"> Company Name 2 
     </div> 
    </div> 

    <div class="editor-row"> 
     <label>Project</label> 
     <div data-bind="visible: !isEditMode()"> 
      <span data-bind="text: selectedProject.Name"></span> 
     </div> 
     <div data-bind="visible: isEditMode()"> 
      <select data-bind="options: selectedCustomer().projects, optionsText: 'Name', value: selectedProject"></select> 
     </div> 
    </div> 

    <div> 
     <button data-bind="click: function() { turnOnEditMode() }">Edit</button> 
     <button data-bind="click: function() { turnOffEditMode() }">Cancel</button> 
    </div> 
</div> 

<hr/> 

<div data-bind="text: ko.toJSON($root)"></div> 

function ajaxCallGetProjectsByCustomer(customerId) { 
    var database = '[{"CustomerId": 1, "Name":"Company Name 1", "Projects": [ { "ProjectId": "11", "Name": "project 11" }, { "ProjectId": "12", "Name": "project 12" }, { "ProjectId": "13", "Name": "project 13" }] }, {"CustomerId": 2, "Name": "Company Name 2", "Projects": [ { "ProjectId": "21", "Name": "project 21" }, { "ProjectId": "22", "Name": "project 22" }, { "ProjectId": "23", "Name": "project 23" }] }]'; 

    var json = ko.utils.parseJson(database); 
    //console.log('parseJson(database) - ' + json); 

    //ko.utils.arrayForEach(json, function(item) { 
    // console.log('CustomerId: ' + item.CustomerId); 
    //}); 

    return ko.utils.arrayFirst(json, function(item){ 
     return item.CustomerId == customerId; 
    }); 
} 

var Customer = function(id, name, projects) { 
    var self = this; 

    this.id = ko.observable(id); 
    this.CompanyName = ko.observable(name); 

    this.projects = ko.observableArray(ko.utils.arrayMap(projects, function(item) { 
     return new Project(item.ProjectId, item.Name); 
    })); 
}; 

Customer.load = function(id) { 
    var data = ajaxCallGetProjectsByCustomer(id); 

    var customer = new Customer(
     data.CustomerId, 
     data.Name, 
     data.Projects); 
}; 

var Project= function(id, name) { 
    this.id = id; 
    this.Name = ko.observable(name); 
}; 

var QuoteViewModel = function() { 
    var self = this; 

    $customerData = $('#customerData'); // data from html elements 
    $projectData = $('#projectData'); 

    // intial values to display from html data 
    var customer = new Customer (
     $customerData .attr('data-id'), 
     $customerData .attr('data-companyName'), 
     [{"ProjectId": $projectData .attr('data-id'), "Name": $projectData .attr('data-name')}] 
    ) 

    this.selectedCustomer = ko.observable(customer); 
    this.selectedProject = ko.observable($projectData.attr('data-id')); 

    this.isEditMode = ko.observable(false); 

    this.selectedCustomer.subscribe(function(){ 
     // todo: load customer projects from database api when editing 
    }); 

    this.turnOnEditMode = function() { 
     var customerId = self.selectedCustomer().id(); 
     console.log('customerId: ' + customerId); 
     Customer.load(customerId); 
     self.isEditMode(true); 
    }; 

    this.turnOffEditMode = function() { 
     self.isEditMode(false); 
    }; 
}; 

var viewModel = new QuoteViewModel(); 
ko.applyBindings(viewModel); 
+0

당신이하려는 것을보기가 정말로 어렵습니다. 편집 버튼을 클릭 할 때마다 thingamabob을 다시로드합니까? jquery dom 물건이 필요한 이유를 이해하지 못합니다. 아마도이 문제와 관련이 없습니다. 무슨 일이 일어나는지 정확히 설명해 주시겠습니까? – madcapnmckay

+0

좀 더 자세한 설명을 추가했습니다. 목표는 읽기 전용 모드로 레코드를 표시하고 필요할 때 서버에서 컨트롤에 관련 데이터를로드 할 수있는 옵션이있는 옵션을 사용하는 것입니다. 정식 버전에서는 다른 thingamabob을 선택하는 옵션이 있지만 문제는 초기 값을 편집하는 것만으로 모든 데모가 수행됩니다. –

답변

0

한 초기 값 당신은

this.dongle = ko.observable($dongleData.attr('data-id')); 

이 문자열 값 "3"이 될 것입니다로드합니다. 동글 html 선택 요소가 개체를 실제로 저장/예상하는 경우{ "Id": "3", "Name": "dongle 3" }.

올바른 초기 값을 가져 와서 편집 할 수있는 작동 버전입니다. 당신이 특정 값이 아닌 전체 동글/위젯 개체를 저장해야하는 경우

http://jsfiddle.net/madcapnmckay/28FVr/5/

, 당신은 단지 ID를 저장하기 위해 optionsValue 속성을 사용할 수 있습니다. 여기 같은 방식으로 작동합니다.

http://jsfiddle.net/madcapnmckay/VnjyT/4/

편집

좋아, 내가 당신을 위해 작업 버전이있다. 내가 바꾼 모든 것과 그 이유를 요약하려고 노력할 것이다.

http://jsfiddle.net/madcapnmckay/jXr8W/

고객 정보가

하면 데이터에서 새 이름을 결정하는 방법 고객을 없었다로드 할 때 고객의 이름은 그래서 ajaxCallGetProjectsByCustomer JSON에 저장되지 않은 작업을 얻으려면 받았습니다. "Company Name 1"이라는 이름으로 json의 각 고객에게 Name 속성을 추가했습니다.

는 프로젝트 컬렉션에 동글 원래 명시된 바와 같이 문제는 여기에 있었다

작동하도록합니다. 당신은 을 $projectData.attr('data-id')으로 초기화합니다.이 값은 문자열 값 13과 동일합니다. 선택 목록이 실제로 프로젝트 객체 자체를 저장/예상하는 방식으로 구성되어 있기 때문에 올바르지 않습니다. 이 id 할당을 객체 할당으로 변경하면 프로젝트의 초기 값이 올바르게 작동합니다.

var project = ko.utils.arrayFirst(customer.projects(), function(project){ 
    return project.id == Number($projectData.attr('data-id')); 
}); 

this.selectedProject = ko.observable(project); 

참고 html에 경미한 오류가 발생했습니다. selectedProject.Name은 selectedProject()입니다. Name. 별거 아니야.

나는 꽤 쉽게 알아낼 수있을 것이라고 확신합니다. 다음 비트는 진짜 문제가있는 곳입니다. 수정 버튼을 클릭 할 때마다 고객이 다시로드됩니다. 이것은 이상하게 보입니다. 그런 접근법을 재고하고 싶을 수도 있습니다.

그러나 id로 서버에서 고객 개체를로드하면 어떻게됩니까? selectedCustomer observable에 할당하십시오. 실제로 제대로 작동합니다. 그러나 드롭 다운은 selectedCustomer().projectsviewModel.selectedProject에 바인딩되어 있기 때문에 selectedProject는 selectedCustomer(). projects의 멤버입니다. 오브젝트의 경우, 평등 운영자는 referencesCustomer 값을 겹쳐 쓸 때 원래 selectedProject가 연관된 고객과 함께 소멸 되었기 때문에 참조가 일치하는지 여부를 평가하고 있습니다. ID가 동일하다는 사실은 부적합합니다.

나는 이것을 해결하기 위해 해킹을했다.

var oldProjectId = viewModel.selectedProject().id; 
viewModel.selectedCustomer(customer); 

var sameProjectDifferentInstance = ko.utils.arrayFirst(customer.projects(), function(project){ 
    return project.id == oldProjectId; 
}); 

viewModel.selectedProject(sameProjectDifferentInstance || customer.projects()[0]); 

이 새로운 고객을 할당하기 전에 이전 projectId를 저장, 새로운 고객 객체에서 프로젝트 객체를 검색하고 찾을 수없는 경우 나 처음에 기본값을 할당합니다.

개체를로드하고 라이프 사이클을 처리하는 방법에 대해 다시 생각해 보시기 바랍니다. 현재 프로젝트에 포함 된 전체 프로젝트 목록과 함께 현재 개체를 보유하고 있으면 수정하기 위해 다시로드 할 필요가 없습니다. 간단히 편집 한 다음 서버로 다시 보내면됩니다.

서버에서 json을 html dom 요소 대신 js 변수에 보관하는 것이 더 쉽습니다. 예 :

<script>var projectInitialData = '@Model.ProjectInitialData.toJSON()';</script> 

희망이 도움이됩니다.

+0

madcapnmckay 및 제안 사항을 검토해 주셔서 감사합니다. 나는 서버 쪽 MVC 접근 방식을 반영하는 녹아웃 작업 방법을 찾고있다. 해당 ID 대신 객체를 선택한 다음 UI의 다른 영역 및 상태에서 해당 객체를 참조합니다. 이 샘플과 유사 : http://jsfiddle.net/mathewvance/Krc2L/ 다음은 동적으로 채워진 선택 목록을 제자리에서 편집하기위한 이전 시도입니다. http://jsfiddle.net/mathewvance/TZeBc/ –

+0

무슨 뜻입니까? 서버 측 MVC 접근법을 반영 하는가?두 번째 예제에서 상황을 혼란스럽게하는 것은 this.isEditMode.subscribe 함수입니다.이 함수는 편집 버튼을 클릭 할 때마다 thingamabob을 다시로드합니다. 시작시 ID 44가로드되어 편집을 클릭하면 다시로드되고 취소/다시 편집을 클릭하면 다시로드됩니다. 매번 다시로드하면 상태를 저장할 수 있음을 어떻게 알 수 있습니까? 나는 그것을 잘 이해한다면 당신을 위해이 일을 얻을 수 있습니다. :) – madcapnmckay

+0

BTW this.isEditMode.subscribe는 isEditMode를 설정하는 편집을 호출합니다. 그것은 현재 아프지 않지만 그것이 합리적이지 않습니다. – madcapnmckay

관련 문제