2013-04-10 3 views
0

녹아웃을 사용하여 선택 사항 (이름 목록)이 있는데이 옵션은 다른 녹아웃 바인딩 데이터 (사람)에 바인딩되어 있습니다. 어떤 사람의 이름이 변경되면 그 사람의 이름에 바인딩 된 선택 옵션의 값이 올바르게 갱신됩니다. 그러나 이미 선택한 사람을 선택하면 선택 항목의 선택 항목이 보존되지 않습니다. 바운드 데이터가 변경 될 때 선택한 인덱스가 변경되지 않도록하려면 어떻게해야합니까?

라이브 예를 들어이 jsFiddle를 참조하십시오 http://jsfiddle.net/DbBZQ/

  1. 선택 "제인"목록에서.
  2. "Jane"이라는 이름을 다른 것으로 변경하십시오 (예 : "Jane Doe").
  3. 선택 항목이 첫 번째 항목으로 돌아갑니다.

내재 된 값이 변경된 경우에도 같은 옵션 색인에 선택을 적용하려면 어떻게해야합니까? 선택을 유지하기 위해 녹아웃을 지시하는 방법이 있습니까? 아니면 JS를 사용하여 별도로해야합니까? 선택된 값이 변경 이름 속성에 직접 일치하기 때문에 선택이 손실

전체 코드 예제

<!DOCTYPE html> 

<html lang="en" xmlns="http://www.w3.org/1999/xhtml"> 
    <head> 
     <meta charset="utf-8" /> 
     <title></title> 
     <script type="text/javascript" src="http://knockoutjs.com/downloads/knockout-2.2.1.js"></script> 
     <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script> 
     <script type="text/javascript"> 
      var data = 
      { 
       people: ko.observableArray(
       [ 
        { name: ko.observable("Jim") }, 
        { name: ko.observable("Jane") }, 
        { 
         name: ko.observable("Sam"), 
         subordinates: ko.observableArray(
         [ 
          { 
         name: ko.observable("Tambone"), 
           subordinates: ko.observableArray(
           [ 
            { name: ko.observable("Edward") }, 
            { name: ko.observable("Kristy") }, 
            { name: ko.observable("Thomas") }, 
            { name: ko.observable("Andy") } 
           ]) 
          }, 
          { name: ko.observable("Jules") } 
         ]) 
        } 
       ]) 
      }; 
      var allNames = ko.computed(function() 
      { 
       var names = []; 
       var selector = function (name, indent) 
       { 
        var option = 
        { 
         value: name, 
         text: (indent || "") + name 
        }; 

        return option; 
       }; 

       for (var i = 0; i < data.people().length; i++) 
       { 
        names.push(selector(data.people()[i].name())); 
        addSubordinates(names, 1, data.people()[i].subordinates, selector); 
       } 

       return names; 
      }); 

      function addSubordinates(names, depth, subordinates, selector) 
      { 
       if (subordinates != null) 
       { 
        var indentText = ""; 

        for (var i = 0; i < depth; i++) 
         indentText += ". . "; 

        for (var i = 0; i < subordinates().length; i++) 
        { 
         names.push(selector(subordinates()[i].name(), indentText)); 
         addSubordinates(names, depth + 1, subordinates()[i].subordinates, selector); 
        } 
       } 
      } 
     </script> 
    </head> 
    <body> 
     <div data-bind="foreach: data.people"> 
      <input type="text" data-bind="value: name" /><br /> 
     </div> 
     <a href="JavaScript:data.people.push({ name: ko.observable('New Person') });">Add Person</a> 

     <br /><br /><br /> 

     <select data-bind="options: allNames, optionsValue: 'value', optionsText: 'text', optionsCaption: 'All Names...'" /> 

     <script type="text/javascript"> 
      ko.applyBindings(); 
     </script> 
    </body> 
</html> 

답변

1

이유입니다. 결과적으로 선택한 값이 데이터 소스 (allNames)에 더 이상 존재하지 않습니다.

당신이 선택을 유지하려면, 당신은 몇 가지 옵션이 있습니다

  1. 은 인덱스를 추적하고, 값이에
  2. 바인딩 선택된 값을 변경 후 재설정으로 해킹을 구현 변경되지 않는 속성.

선택한 값으로 사용할 수있는 불변 속성이 있습니까?

예를 들어 데이터 소스의 개체에 id 속성을 추가하고이를 이름 대신 선택한 값으로 사용합니다. 이 방법은 당신이 기대하는 작품 :

<!DOCTYPE html> 

<html lang="en" xmlns="http://www.w3.org/1999/xhtml"> 
    <head> 
     <meta charset="utf-8" /> 
     <title></title> 
     <script type="text/javascript" src="http://knockoutjs.com/downloads/knockout-2.2.1.js"></script> 
     <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script> 
     <script type="text/javascript"> 
      var data = 
      { 
       people: ko.observableArray(
       [ 
        { id: 1, name: ko.observable("Jim") }, 
        { id: 2, name: ko.observable("Jane") }, 
        { 
         id: 3, name: ko.observable("Sam"), 
         subordinates: ko.observableArray(
         [ 
          { 
         id: 4, name: ko.observable("Tambone"), 
           subordinates: ko.observableArray(
           [ 
            { id: 5, name: ko.observable("Edward") }, 
            { id: 6, name: ko.observable("Kristy") }, 
            { id: 7, name: ko.observable("Thomas") }, 
            { id: 8, name: ko.observable("Andy") } 
           ]) 
          }, 
          { id: 9, name: ko.observable("Jules") } 
         ]) 
        } 
       ]) 
      }; 
      var allNames = ko.computed(function() 
      { 
       var names = []; 
       var selector = function (id, name, indent) 
       { 
        var option = 
        { 
         value: id, 
         text: (indent || "") + name 
        }; 

        return option; 
       }; 

       for (var i = 0; i < data.people().length; i++) 
       { 
        names.push(selector(data.people()[i].id, data.people()[i].name())); 
        addSubordinates(names, 1, data.people()[i].subordinates, selector); 
       } 

       return names; 
      }); 

      function addSubordinates(names, depth, subordinates, selector) 
      { 
       if (subordinates != null) 
       { 
        var indentText = ""; 

        for (var i = 0; i < depth; i++) 
         indentText += ". . "; 

        for (var i = 0; i < subordinates().length; i++) 
        { 
         names.push(selector(subordinates()[i].id,subordinates()[i].name(), indentText)); 
         addSubordinates(names, depth + 1, subordinates()[i].subordinates, selector); 
        } 
       } 
      } 
     </script> 
    </head> 
    <body> 
     <div data-bind="foreach: data.people"> 
      <input type="text" data-bind="value: name" /><br /> 
     </div> 
     <a href="JavaScript:data.people.push({ name: ko.observable('New Person') });">Add Person</a> 

     <br /><br /><br /> 

     <select data-bind="options: allNames, optionsValue: 'value', optionsText: 'text', optionsCaption: 'All Names...'" /> 

     <script type="text/javascript"> 
      ko.applyBindings(); 
     </script> 
    </body> 
</html> 

편집 : 그것은이 항목의 인덱스를 반환하는 ko.computed되었다 있도록이 value 속성을 설정 한 경우 어떤 대안으로 ? 이와 같이 :

var allNames = ko.computed(function() 
{ 
    var names = []; 
    var selector = function (item, name, indent) 
    { 
     var option = 
     { 
      value: ko.computed(function(){ return data.people().indexOf(item);}), 
      text: (indent || "") + name 
     }; 

     return option; 
    }; 

    for (var i = 0; i < data.people().length; i++) 
    { 
     names.push(selector(data.people()[i], data.people()[i].name())); 
     addSubordinates(names, 1, data.people()[i].subordinates, selector); 
    } 

    return names; 
}); 

function addSubordinates(names, depth, subordinates, selector) 
{ 
    if (subordinates != null) 
    { 
     var indentText = ""; 

     for (var i = 0; i < depth; i++) 
      indentText += ". . "; 

     for (var i = 0; i < subordinates().length; i++) 
     { 
      names.push(selector(subordinates()[i],subordinates()[i].name(), indentText)); 
      addSubordinates(names, depth + 1, subordinates()[i].subordinates, selector); 
     } 
    } 
} 
+0

고맙다. 나는'persistelectedIndex'와 같은 간단한 바인딩 속성을 원했다. 임의의 ID에 바인딩하는 것은 괜찮습니다. 내 목록에서 원하는 "것"중 일부는 ID가 있지만 다른 것은 사용하지 않습니다 (예 : 아직 DB에 커밋되지 않은 새 항목 추가). –

+0

글쎄, 그건 생각이야. 'value'가 항목에 대한 색인을 반환하는 계산 인 경우 어떻게합니까? 나는 이것을 설명하기 위해 해답을 편집했다. –

+0

값을'$ index'로 설정할 수도 있습니다 (아마도 시도하지 않았습니다). –

관련 문제