2012-08-30 4 views
0

KO로 곧 시작하여 곧 프로젝트에 참여시키고 싶습니다. 여가 시간에 나는 직장에서 웹 서비스를 해왔다. 이것은 기본적으로 데이터로 무엇인가를 시작한 다음 다른 작업을하는 것으로 시작되었다. 그래서 처음에는 마약 이름 목록을 반환했습니다. 좋아, 반환 된 결과의 개수를 추가합시다. 자, 각 약물의 세부 사항을 모달로 채 웁니다. 좋아, 마약 이름을 수정합시다. 아니 진짜 운율이나 이유, 그냥 물건을 들고와 KO 놀아.observableArray에서 업데이트를 위해 데이터를 관리하는 방법을 잘 모름

어디서나 데이터를 실제로 관리 할 수있는 방법을 모르겠다. 내가 가진 것을 살펴보고 문제를 설명하는 스크린 샷을 만들었습니다.

  1. 은 "Y"버튼을 클릭하여 검색 결과를 얻을

    http://i.imgur.com/5qNWQ.jpg

    . 나는 다음 약물 이름이 업데이트됩니다
  2. 버튼 "저장"
  3. 나는 약물 이름을 편집 에게
  4. 내가 모달 창에 그 약물에 대한 상세보기를 얻을 "야스민 (28)"약물을 선택하고 클릭 모달 창
  5. 나는 DOM의 해당 부분을 크롤링하고 이전 약물 이름을 신약 이름으로 바꾸어 검색 결과에서 약물 이름을 업데이트하고 약물 이름을 업데이트합니다.

이 문제는 KO의 관찰 가능한 특성을 이용하지 못합니다 ... 모달을 닫고 "Yasmin 28"약물 링크를 다시 클릭하면 모달에 " Yasmin 28 "방금 변경 한 것이 아닙니다 ("멋진 ").

내 observableArray에서 속성이 변경되면 추적하는 방법을 잘 모르겠습니다. 나는 관찰 가능한 두 개의 배열을 만들었고 하나는 검색 결과에 대한 약물 이름 목록을 보유하고 다른 하나는 약물의 세부 사항을 보유합니다. 나는 또한 현재의 약물 이름을 관찰 할 수있게 만들었습니다.

어디에서나 약물 이름을 추적하기 위해 내가해야 할 일을 설명 할 수 있습니까? 아래 코드와 JSON을 포함 시켰습니다. 이 데이터의 중복을 잡고 혼란을 야기으로

<div id="shell"> 
    <button class="load" value="j">j</button> 
    <button class="load" value="k">k</button> 
    <button class="load" value="x">x</button> 
    <button class="load" value="y">y</button> 
    <button class="load" value="z">z</button> 
    <p id="loading"><img src="#{facesContext.externalContext.requestContextPath}/img/spinner.gif"/></p> 

    <h3 data-bind="visible: drugList().length > 0"><span data-bind="text: count" class="count"></span> records returned</h3> 

    <ul data-bind="foreach: drugList"> 
     <li> 
      <span data-bind="text: drugName" class="results_drug_name"></span> 
      <a data-bind="click: $root.showDetails" href="#" class="show">show details</a> 
     </li> 
    </ul> 
</div> 

<!-- start modal: drug details --> 
<div id="dialog" data-bind="jqDialog: {autoOpen: false, title: drugName}"> 
    <p id="dialog_save_message" class="message_success">Changes saved successfully!!!!!!!!</p> 

    <table data-bind="foreach: drugListDetails" class="table" width="100%" cellpadding="0" cellspacing="0" border="1"> 
     <tr> 
      <th scope="row">pdlId</th> 
      <td data-bind="text: pdlId"></td> 
     </tr> 
     <tr> 
      <th scope="row">drugName</th> 
      <td> 
       <span data-bind="text: $root.drugName" class="readonly"></span> 
       <input id="edit_drugname" class="edit_textfield" type="text" value="" size="35" /> 
       <button data-bind="click: $root.editSave" class="edit_buttons save">Save</button> 
       <button data-bind="click: $root.editCancel" class="edit_buttons cancel">Cancel</button> 
       <ul class="detail_actions"> 
        <li><a data-bind="click: $root.edit" href="#" class="edit">edit</a></li> 
       </ul> 
      </td> 
     </tr> 

     <tr> 
      <th scope="row">dosageFormDesc</th> 
      <td data-bind="text: dosageFormDesc"></td> 
     </tr> 
     <tr> 
      <th scope="row">strength</th> 
      <td data-bind="text: strength"></td> 
     </tr> 
     <tr> 
      <th scope="row">activeIngredient</th> 
      <td data-bind="text: activeIngredient"></td> 
     </tr> 
     <tr> 
      <th scope="row">tier</th> 
      <td data-bind="text: tier"></td> 
     </tr> 
     <tr> 
      <th scope="row">ancillaryCharge</th> 
      <td data-bind="text: ancillaryCharge"></td> 
     </tr> 
     <tr> 
      <th scope="row">preauthCode</th> 
      <td data-bind="text: preauthCode"></td> 
     </tr> 
     <tr> 
      <th scope="row">quantityLimit</th> 
      <td data-bind="text: quantityLimit"></td> 
     </tr> 
     <tr> 
      <th scope="row">prefAlternative</th> 
      <td data-bind="text: prefAlternative"></td> 
     </tr> 
     <tr> 
      <th scope="row">specialtyDrug</th> 
      <td data-bind="text: specialtyDrug"></td> 
     </tr> 
     <tr> 
      <th scope="row">partbCob</th> 
      <td data-bind="text: partbCob"></td> 
     </tr> 
     <tr> 
      <th scope="row">drugClassGroupId</th> 
      <td data-bind="text: drugClassGroupId"></td> 
     </tr> 
     <tr> 
      <th scope="row">drugClassId</th> 
      <td data-bind="text: drugClassId"></td> 
     </tr> 
     <tr> 
      <th scope="row">drugClass</th> 
      <td data-bind="text: drugClass"></td> 
     </tr> 
     <tr> 
      <th scope="row">genericInd</th> 
      <td data-bind="text: genericInd"></td> 
     </tr> 
     <tr> 
      <th scope="row">tip</th> 
      <td data-bind="text: tip"></td> 
     </tr> 
    </table> 
</div> 
<!-- end modal: drug details --> 

<script> 
$(function() { 
    $('.load').click(function() { 
     var $letter = $(this).attr('value'); 

     //show spinner 
     $('#loading').show(); 

     //load in drug list data 
     $.getJSON('/PreferredDrugList/service/preferredDrugs/' + $letter, function(data) { 
      //hide spinner 
      $('#loading').hide(); 

      //replace drugList observableArray data 
      //preferredDrugs is an array of objects, each elem is an individual drug 
      myViewModel.drugList(data.preferredDrugs); 

      //replace count observable data 
      myViewModel.count(data.count); 
     });//end getJSON 
    });//end click 

    //setup modal dialog options 
    $('#dialog').dialog({ 
     autoOpen: false, 
     closeOnEscape: true, 
     modal: true, 
     width:850, 
     height:500 
    }); 

});//end ondomready 

//custom binding to initialize a jQuery UI dialog 
ko.bindingHandlers.jqDialog = { 
    init: function(element) { 
     ko.utils.domNodeDisposal.addDisposeCallback(element, function() { 
      $(element).dialog("destroy"); 
     }); 
    }, 
    update: function(element, valueAccessor) { 
     var options = ko.toJS(valueAccessor()); 

     if (options) { 
      $(element).dialog(options); 
     }   
    } 
}; 

var myViewModel = { 
    count:    ko.observable(),  //# of records returned 
    drugList:   ko.observableArray(), //list of drug names - an array of objects 
    drugListDetails: ko.observableArray(), //list of individual drug details 
    drugName:   ko.observable(),  //current drug name 

    //show drug details in modal 
    //func gets passed the current observableArray elem (the individual drug info we clicked on, this is an object) 
    showDetails: function(obj) { 
     //replace current drug name observable data 
     myViewModel.drugName(obj.drugName); 

     //replace drugListDetails observableArray data, otherwise we'll append data to the modal 
     myViewModel.drugListDetails([]); 

     //push individual drug info to details observableArray 
     myViewModel.drugListDetails.push(obj); 

     //show dialog 
     $('#dialog').dialog('open'); 

     return false; 
    }, 

    //edit drug from modal 
    edit: function(obj) { 
     var $edit   = $('#dialog').find('td .edit'), 
      $currentTD = $edit.closest('td'); 

     $currentTD.addClass('editing'); 
     $currentTD.find('.readonly').hide(); 
     $currentTD.find('.edit_textfield').show().select(); 
     $currentTD.find('.edit_buttons').show(); 

     return false; 
    }, 

    //save an edit 
    editSave: function(obj) { 
     alert('TODO save back to the server'); 

     var $saveBtn = $('#dialog').find('td .save'), 
      $currentTD = $saveBtn.closest('td'), 
      newDrugName = $('#edit_drugname').val(), 
      $dialog_save_message = $('#dialog_save_message'); 

     //save new drug name to observable 
     myViewModel.drugName(newDrugName); 

     $currentTD.removeClass('editing'); 
     $currentTD.find('.readonly').show(); 
     $currentTD.find('.edit_textfield').hide(); 
     $currentTD.find('.edit_buttons').hide(); 

     $dialog_save_message.slideDown('slow', function() { 
      //animation complete 
      setTimeout(function() { 
       $dialog_save_message.slideUp(); 
      }, 3000); 
     }); 

     //cheat and update search results list with new drug name 
     $('.results_drug_name').each(function(index, elem) { 
      var $text = $(this).text(); 

      if ($text === obj.drugName) { 
       $(this).text(newDrugName).addClass('edited'); 
      } 
     }); 
    }, 

    //cancel an edit 
    editCancel: function(obj) { 
     var $cancelBtn  = $('#dialog').find('td .cancel'), 
      $currentTD = $cancelBtn.closest('td'); 

     $currentTD.removeClass('editing'); 
     $currentTD.find('.readonly').show(); 
     $currentTD.find('.edit_textfield').hide(); 
     $currentTD.find('.edit_buttons').hide(); 
    } 
}; 

ko.applyBindings(myViewModel); 

<!--what's returned from the web service--> 
<pre> 
{ 
    "preferredDrugs": [(8) 
     { 
      "pdlId": 8090, 
      "drugName": "y-cof-dmx", 
      "dosageFormDesc": "Liquid", 
      "strength": "4MG/5ML; 15MG/5ML; 7.5MG/5ML", 
      "activeIngredient": "BROMPHENIRAMINE MALEATE; DEXTROMETHORPHAN HYDROBROMIDE; PHENYLEPHRINE HYDROCHLORIDE", 
      "tier": "OTC", 
      "ancillaryCharge": "NA", 
      "preauthCode": " ", 
      "quantityLimit": " ", 
      "prefAlternative": null, 
      "specialtyDrug": " ", 
      "partbCob": " ", 
      "drugClassGroupId": 74, 
      "drugClassId": 152, 
      "drugClass": "Respiratory Tract Agents » Antitussives", 
      "genericInd": "1", 
      "tip": " " 
     },- 
     { 
      "pdlId": 13417, 
      "drugName": "YASMIN 28", 
      "dosageFormDesc": "Tablet", 
      "strength": "3MG; 0.03MG", 
      "activeIngredient": "DROSPIRENONE; ETHINYL ESTRADIOL", 
      "tier": "3", 
      "ancillaryCharge": "AC", 
      "preauthCode": " ", 
      "quantityLimit": "28.0 tabs each 28 days", 
      "prefAlternative": "ethinyl estradiol/drospirenone", 
      "specialtyDrug": " ", 
      "partbCob": " ", 
      "drugClassGroupId": 3, 
      "drugClassId": 200, 
      "drugClass": "Hormones and Synthetic Substitutes » Contraceptives", 
      "genericInd": "0", 
      "tip": " " 
     },- 
     { 
      "pdlId": 24765, 
      "drugName": "YAZ", 
      "dosageFormDesc": "Tablet", 
      "strength": "3MG; 0.02MG", 
      "activeIngredient": "DROSPIRENONE; ETHINYL ESTRADIOL", 
      "tier": "3", 
      "ancillaryCharge": "AC", 
      "preauthCode": " ", 
      "quantityLimit": "28.0 tabs each 28 days", 
      "prefAlternative": "ethinyl estradiol/drospirenone", 
      "specialtyDrug": " ", 
      "partbCob": " ", 
      "drugClassGroupId": 3, 
      "drugClassId": 200, 
      "drugClass": "Hormones and Synthetic Substitutes » Contraceptives", 
      "genericInd": "0", 
      "tip": " " 
     },- 
     { 
      "pdlId": 2252, 
      "drugName": "YERVOY", 
      "dosageFormDesc": "Solution", 
      "strength": "50MG/10ML", 
      "activeIngredient": "IPILIMUMAB", 
      "tier": "NC", 
      "ancillaryCharge": "NA", 
      "preauthCode": " ", 
      "quantityLimit": " ", 
      "prefAlternative": null, 
      "specialtyDrug": " ", 
      "partbCob": " ", 
      "drugClassGroupId": 115, 
      "drugClassId": 1, 
      "drugClass": "Antineoplastic Agents", 
      "genericInd": "0", 
      "tip": " " 
     },- 
     { 
      "pdlId": 20993, 
      "drugName": "YERVOY", 
      "dosageFormDesc": "Solution", 
      "strength": "200MG/40ML", 
      "activeIngredient": "IPILIMUMAB", 
      "tier": "NC", 
      "ancillaryCharge": "NA", 
      "preauthCode": " ", 
      "quantityLimit": " ", 
      "prefAlternative": null, 
      "specialtyDrug": " ", 
      "partbCob": " ", 
      "drugClassGroupId": 115, 
      "drugClassId": 1, 
      "drugClass": "Antineoplastic Agents", 
      "genericInd": "0", 
      "tip": " " 
     },- 
     { 
      "pdlId": 564, 
      "drugName": "YF-VAX", 
      "dosageFormDesc": "Injection", 
      "strength": "0", 
      "activeIngredient": "YELLOW FEVER VACCINE", 
      "tier": "NC", 
      "ancillaryCharge": "NA", 
      "preauthCode": " ", 
      "quantityLimit": " ", 
      "prefAlternative": null, 
      "specialtyDrug": " ", 
      "partbCob": " ", 
      "drugClassGroupId": 79, 
      "drugClassId": 284, 
      "drugClass": "Serums, Toxoids and Vaccines » Vaccines", 
      "genericInd": "0", 
      "tip": " " 
     },- 
     { 
      "pdlId": 8910, 
      "drugName": "yodefan-nf chest congestion", 
      "dosageFormDesc": "Liquid", 
      "strength": "200MG/5ML", 
      "activeIngredient": "GUAIFENESIN", 
      "tier": "OTC", 
      "ancillaryCharge": "NA", 
      "preauthCode": " ", 
      "quantityLimit": " ", 
      "prefAlternative": null, 
      "specialtyDrug": " ", 
      "partbCob": " ", 
      "drugClassGroupId": 84, 
      "drugClassId": 155, 
      "drugClass": "Respiratory Tract Agents » Expectorants", 
      "genericInd": "1", 
      "tip": " " 
     },- 
     { 
      "pdlId": 13101, 
      "drugName": "YODOXIN", 
      "dosageFormDesc": "Tablet", 
      "strength": "650MG", 
      "activeIngredient": "IODOQUINOL", 
      "tier": "3", 
      "ancillaryCharge": "NA", 
      "preauthCode": " ", 
      "quantityLimit": " ", 
      "prefAlternative": "iodoquinol", 
      "specialtyDrug": " ", 
      "partbCob": " ", 
      "drugClassGroupId": 164, 
      "drugClassId": 277, 
      "drugClass": "Anti-infective Agents » Antiprotozoals", 
      "genericInd": "0", 
      "tip": " " 
     }- 
    ],- 
    "count": 8 
} 
</pre> 

</script> 
+0

왜 두 가지 약품 목록을 사용합니까? 두 가지 모두에 동일한 목록을 사용하는 것이 가장 좋은 이유는 무엇입니까? –

+0

그건 내가 알아 내지 못하는 것입니다. 하나의 observableArray로 어떻게 작업할까요? 서버에서 JSON 데이터를로드 할 때 myViewModel.drugList (data.preferredDrugs); (foreach를 사용하여 반복 처리 할 객체의 배열) 어떻게 작동시킬 수 있습니까? myViewModel.drugList (data); 내 JSON 구조에서 더 높은 수준입니까? preferredDrugs 배열을 드릴 다운 할 수 없습니다. –

답변

1

먼저drugListDetails 배열을 제거합니다. 둘째

,과 관찰 배열에서 data.preferredDrugs를 매핑 ko.mapping.fromJSko.mapping.toJS를 사용합니다. 그러면 knockout에서 배열의 모든 요소에 대한 GUI의 변경 사항을 추적 할 수 있습니다. 이에 대한 문서는 here입니다.

mapping 플러그인을 사용하지 않으려는 경우 수동으로 매핑을 수행 할 수도 있습니다. 셋째

falsedata.preferredDrugs 배열의 각 항목에 해당 기본값을 새로운 showDetails 요소를 추가 할 수 있습니다. 대화 상자를 표시할지 여부를 결정하기 위해 다음 단계에서 사용됩니다. $root.showDetails이 호출되면 showDetails 요소를 토글해야합니다.

넷째drugList 배열을 사용하고 각각의 약물 요소의 showDetails 값의 visible 값을 바인딩 대화 div을 수정합니다. 이렇게하면 여러 개의 숨겨진 대화 상자가 만들어 지므로 각각의 id 값을 변경할 수 있습니다.

+0

매핑 플러그인을 지금보고 있습니다. 정적 데이터로 작업 할 수는 있지만 서버에서 json으로로드 할 때 작동하지 않는 것 같습니다. 그 플러그인에 대한 머리를 주셔서 감사합니다, 내가 필요한 것 같습니다. –