选择正确的选项时,选择列表不会呈现。我已经尝试了很多不同的方法,包括计算选择的observable(this.selected = ko.computed(return parseInt(selected(),10)== this.id;))并在数组函数中查找。
在生产中,dataArea元素将填充服务器端数据。使用带有“data-”属性的div可以将服务器端和客户端脚本分开(我发现这有助于设计人员)。
记录将以非编辑模式显示,并且可以通过单击编辑按钮进行编辑。在编辑模式下,记录的初始值显示在输入控件中。您可以选择说,选择其他客户并让表单加载新的关联项目。加载新客户将按预期重置项目列表。
因此,虽然加载新客户会很有效,但是过渡到编辑导致问题的当前值。所选项目需要显示在下拉列表中。如果选择了新客户,则列表会填充新选项,并且不需要默认值。
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 :(得分:0)
您加载的初始值
this.dongle = ko.observable($dongleData.attr('data-id'));
这将是字符串值“3”。加密狗html选择元素实际上正在保存/期望检索对象 { "Id": "3", "Name": "dongle 3" }
。
这是一个可以获得正确初始值并允许编辑的工作版本。
http://jsfiddle.net/madcapnmckay/28FVr/5/
如果您需要保存特定值而不是整个加密狗/窗口小部件对象,则可以使用optionsValue
属性来存储唯一ID。这是以同样的方式工作。
http://jsfiddle.net/madcapnmckay/VnjyT/4/
修改强>
好的,我有适合你的版本。我会尝试总结一下我改变的一切以及原因。
http://jsfiddle.net/madcapnmckay/jXr8W/
让客户信息正常工作
客户名称未存储在ajaxCallGetProjectsByCustomer
json中,因此当您加载客户时,无法从收到的数据中确定新名称。我在json中为每个客户添加了一个Name属性,名称为“Company Name 1”等。
让项目集合发挥作用
这里的问题与加密狗一样。使用selectedProject
初始化$projectData.attr('data-id')
observable等于字符串值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需要被选为项目()。名称。没什么大不了的。
我相信你可以很容易地找出那些。下一步是真正的问题所在。每次单击编辑按钮时,您都会重新加载客户。这看起来很奇怪,您可能想重新考虑这种方法。
但是,您可以通过id从服务器加载客户对象。将它分配给selectedCustomer observable,这实际上工作正常。但是因为下拉列表绑定到selectedCustomer().projects
和viewModel.selectedProject
,所以它期望selectedProject是selectedCustomer()。projects的成员。在对象的情况下,相等运算符正在评估引用是否匹配,在您的情况下它们不匹配,因为当您覆盖selectedCustomer值时,原始的selectedProject与其关联的客户一起被销毁。 ids相同的事实无关紧要。
我已经实施了一个黑客来解决这个问题。
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,在新客户对象中查找项目对象并将其分配,如果未找到则默认为第一个。
我建议您在加载对象时以及如何处理其生命周期时重新思考。如果您使用完整的项目列表保存当前对象的内存,则无需重新加载它们进行编辑,只需编辑然后将更新发送回服务器。
您可能会发现在js变量而不是html dom元素中更容易从服务器中保存json。 e.g。
<script>var projectInitialData = '@Model.ProjectInitialData.toJSON()';</script>
希望这有帮助。