Data binding 不确定如何在observableArray中管理数据以进行更新

Data binding 不确定如何在observableArray中管理数据以进行更新,data-binding,knockout.js,observable,Data Binding,Knockout.js,Observable,我刚开始和KO一起玩,因为我想把它带到一个即将到来的项目中。在我的业余时间,我一直在工作中使用web服务,这基本上是从处理数据开始,然后再做其他事情。所以首先我只是返回了一份药物名称列表。好的,让我们添加返回结果的计数。好的,让我们在模式中填充各个药物的详细信息。好的,让我们编辑一个药物名称。没有真正的押韵或理由,只是想出一些东西,和柯玩 我不知道如何真正管理我的数据,使其在任何地方都得到更新。我制作了一个屏幕截图,引导您了解我所拥有的并说明问题 点击“y”按钮获取我的搜索结果。然后我选择 “

我刚开始和KO一起玩,因为我想把它带到一个即将到来的项目中。在我的业余时间,我一直在工作中使用web服务,这基本上是从处理数据开始,然后再做其他事情。所以首先我只是返回了一份药物名称列表。好的,让我们添加返回结果的计数。好的,让我们在模式中填充各个药物的详细信息。好的,让我们编辑一个药物名称。没有真正的押韵或理由,只是想出一些东西,和柯玩

我不知道如何真正管理我的数据,使其在任何地方都得到更新。我制作了一个屏幕截图,引导您了解我所拥有的并说明问题

  • 点击“y”按钮获取我的搜索结果。然后我选择 “Yasmin 28”药物
  • 我在模态窗口中获得了该药物的详细视图
  • 我编辑药物名称并单击“保存”按钮
  • 在模式窗口中更新药物名称
  • 我“作弊”并在搜索结果中更新药物名称 对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>
    
    
    J
    K
    x
    Y
    Z
    

    返回的记录

    已成功保存更改

    pdlId 药名 拯救 取消
    剂型描述 力量 活性成分 层 辅助装药 预授权码 数量限制 首选方案 特殊药物 partbCob drugClassGroupId 药物分类 药剂师 通用标识 提示 $(函数(){ $('.load')。单击(函数(){ var$letter=$(this.attr('value'); //显示微调器 $(“#加载”).show(); //加载药物列表数据 $.getJSON('/PreferredDrugList/service/preferredDrugs/'+$letter,函数(数据){ //皮纺纱机 $(“#加载”).hide(); //替换药单数据 //preferredDrugs是一组对象,每个元素都是一种单独的药物 myViewModel.drugList(数据:首选药物); //替换计数可观测数据 myViewModel.count(data.count); });//结束getJSON });//结束单击 //设置模式对话框选项 $('#dialog')。dialog({ 自动打开:错误, closeOnEscape:没错, 莫代尔:是的, 宽度:850, 身高:500 }); });//结束昂多姆雷迪 //用于初始化jQuery UI对话框的自定义绑定 ko.bindingHandlers.jqDialog={ init:函数(元素){ ko.utils.domNodeDisposal.addDisposeCallback(元素,函数(){ $(元素)。对话框(“销毁”); }); }, 更新:函数(元素、值访问器){ var options=ko.toJS(valueAccessor()); 如果(选项){ $(元素)。对话框(选项); } } }; var myViewModel={ 计数:ko.observable(),返回记录的//# drugList:ko.observearray(),//药物名称列表-一个对象数组 drugListDetails:ko.observableArray(),//单个药物详细信息列表 drugName:ko.observable(),//当前药物名称 //在模式中显示药物详细信息 //func通过当前observableArray元素(我们单击的单个药物信息,这是一个对象) showDetails:功能(obj){ //替换当前药物名称可观察数据 myViewModel.drugName(对象drugName); //替换drugListDetails observableArray数据,否则我们会将数据附加到模型中 myViewModel.drugListDetails([]); //将个人药物信息推送到Array的详细信息 myViewModel.drugListDetails.push(obj); //显示对话框 $('dialog')。dialog('open'); 返回false; }, //从modal编辑药物 编辑:功能(obj){ var$edit=$('#dialog').find('td.edit'), $currentTD=$edit.closest('td'); $currentTD.addClass(“编辑”); $currentTD.find('.readonly').hide(); $currentTD.find('.edit_textfield').show().select(); $currentTD.find('.edit_按钮').show(); 返回false; }, //保存编辑 编辑保存:功能(obj){ 艾尔