【问题标题】:Assign default selection from dropdown to model class within another model将下拉列表中的默认选择分配给另一个模型中的模型类
【发布时间】:2025-12-15 09:20:06
【问题描述】:

下面是一些相关代码

标记

<div class="well">
    <input type="button" id="addNewCert" value="Add New Certification" class="btn btn-primary" data-bind="click: addCert"/>
</div>
<table class="table table-striped">
    <thead>
        <tr>
            <th></th>
            <th>Name</th>
            <th>Code</th>
            <th>Description</th>
            <th>Type</th>
        </tr>
    </thead>

    <tbody data-bind="foreach: certs">
        <tr>
            <td><a href="#editCert" data-bind="click: $parent.editCert">Edit</a></td>
            <td><a href="#deleteCert" data-bind="click: $parent.removeCert">Delete</a></td>
            <td data-bind="text: certName"></td>
            <td data-bind="text: certCode"></td>
            <td data-bind="text: description"></td>
            <td data-bind="text: certType.certTypeName"></td>
        </tr>
    </tbody>
</table>

    <div id="selectedCert" data-bind="with: selectedCert">
        <div class="well">
            <div class="row-fluid">
                <div class="span6">

                        <div class="control-group">
                            <h6>Certification Name</h6>
                            <input type="text" id="CertificationName" data-bind="value: certName" style="width:100%;" />
                        </div>
                        <div class="control-group">
                            <h6>Certification Code</h6>
                            <input type="text" id="CertificationCode" data-bind="value: certCode" style="width:50%;" />
                        </div>
                        <div class="control-group">
                            <h6>Description</h6>
                            <textarea ID="Description" data-bind="value: description" style="height:250px;width:480px;"></textarea>
                        </div>
                        <div class="control-group">
                            <h6>Certification Type</h6>
                            <select id="CertificationType" data-bind="options: $parent.availableCertTypes, optionsText: 'certTypeName', optionsValue: 'certTypeId', value: $parent.selectedCertType" style="width:100%;"></select>
                        </div>

                        <div class="control-group">
                            <button class="btn btn-primary" data-bind="click: $parent.save">Save</button>
                            <button class="btn" data-bind="click: $parent.cancel">Cancel</button>
                        </div>

                </div>
            </div>
        </div>
    </div>

视图模型

//Bound to a dropdown and populated by an ajax call listed below
self.availableCertTypes = ko.observableArray([]);
self.selectedCert = ko.observable();

self.addCert = function () {
    self.selectedCert(new Certification({});

    //This line doesn't work :( 
    //self.selectedCert(new Certification(self.availableCertTypes()[0]));

};

//Populates availableCertTypes
    $.getJSON(sf.getServiceRoot('InCertModule') + 'InCert/GetCertTypesByPortal', function (data) {
        //Could call 'self.Certs(self.MapItems(data))' here as that would take the fetched data and populate the viewModel's list of certifications used for binding

        var mappedCertTypes = $.map(data, function (item) {
            return new CertType(item);
        });

        self.availableCertTypes(mappedCertTypes);
    });

型号

var Certification = function (data) {
    if (!data) {
        //If there is no data, pass an empty intialized object, otherwise get an undefined reference
        data = {};
    } else {

        this.certId = ko.observable(data.CertificationId);
        this.certName = ko.observable(data.CertificationName);
        this.certCode = ko.observable(data.CertificationCode);
        this.description = ko.observable(data.Description);
        this.certType = ko.observable(new CertType(data));
        //this.certTypeId = ko.observable(data.CertTypeId);
        //this.certTypeName = ko.observable(data.CertTypeName);
        this.isEditing = ko.observable(false);
        this.isValid = ko.observable(true);
    }
}

var CertType = function (data) {
    this.certTypeId = ko.observable(data.CertTypeId);
    this.certTypeName = ko.observable(data.CertTypeName);
}

我还使用with 绑定设置了编辑功能。这可以正常工作并使我的 CertType 模型正确嵌套,就像这样

  "selectedCert": {
    "certId": 10,
    "certName": "AFC Service Training",
    "certCode": "AFCST",
    "description": "The training required to work AFC service",
    "certType": {
      "certTypeId": 1,
      "certTypeName": "Certification"
    },
    "isEditing": false,
    "isValid": true
  },

但是,我为 addCert 函数尝试了一些组合,以获取 availableCertTypes ObservableArray 中的第一项并分配它。原因是当我将它发布到我的网络服务时,我需要确保在那里选择了一些东西。

我是 Knockout.js 的新手,所以我什至不确定什么是可能的或如何真正完成它,但理想情况下,当我致电 addCert 时,我希望看到与此类似的东西

"selectedCert": {
    //The first item in the observable array 
    "certType": {
      "certTypeId": 1,
      "certTypeName": "Certification"
    },
    "isEditing": false,
    "isValid": true
  }

但我最终得到了

"selectedCert": {
    "certType": {},
    "isEditing": false,
    "isValid": true
  }

如果我需要发布更多代码,请告诉我。非常感谢任何帮助。

编辑 这是一个带有大部分标记的 jsFiddle,虽然它不起作用? http://jsfiddle.net/jtCrw/1/

从 Web 服务获取数组时正确绑定,只是不确定如何在其中硬编码。目前只有这 2 个选项。

【问题讨论】:

    标签: c# javascript knockout.js webforms


    【解决方案1】:

    您的空 certType 问题的根源在于您的设置不匹配/错字。

     self.addCert = function () {
       self.selectedCert(new Certification(self.availableCertTypes()[0]));
     }
    

    导致最终调用this.certType = ko.observable(new CertType(data));

     var CertType = function (data) {
       this.certTypeId = ko.observable(data.CertTypeId); //expecting uppercase property
       this.certTypeName = ko.observable(data.CertTypeName);
     }
    
    self.availableCertTypes = ko.observableArray([
            {
              "certTypeId": 1, //data-bind and this declaration are both lowercase               
              "certTypeName": "Certification"
            },
            {
              "certTypeId": 2,
              "certTypeName": "Training"
            }
        ]);
    

    从当前设置中产生预期结果的修复

    "selectedCertType":{"CertTypeId":1,"CertTypeName":"Certification"}
    

    要获得您所显示/要求的预期结果,请从选择绑定中删除 optionsValue,并将 value 绑定到所选证书的 certType(由 with 绑定提供)

     <select id="CertificationType" 
             data-bind="options: $parent.availableCertTypes, 
                        optionsText: 'CertTypeName', 
                        value: certType"
             style="width:100%;"></select>
    

    结果:

     "selectedCert":{"certType":{"CertTypeId":1,"CertTypeName":"Certification"},"isEditing":false,"isValid":true}
    

    注意事项:如果您想使用现有认证中的数据填充选择,则需要一些特殊注意事项。看看examples of initialization

    【讨论】:

    • 效果很好。除了嵌套 new Certification(CertType(item[index]) 之外,我还可以使用其他分配方式吗?这可能会使事情变得更容易一些?我觉得我现在拥有它的方式只是让自己变得更难。我想学习一些最佳实践,因为我只是在学习。
    • 这取决于您需要为其他活动保留多少信息。嵌套模型没有固有的问题,您只需要注意所涉及的额外复杂性。根据我从小提琴中收集到的上下文,你现在对我来说是有意义的。如果您不需要 certType 对象来做其他任何事情,请将其展平在 Certification 内,使其成为 id 属性并将数据绑定恢复为使用 optionsValue: 'CertTypeId' 这样您只存储简单属性id 而不是一个完整的对象。
    • 考虑到它是一个相当简单的对象,我可能只是将对象展平而不是嵌套它。
    最近更新 更多