我在下面的代码段中创建了一个Knockout模型。
我想要做的是在弹出对话框中创建多对多的关系,从已添加到选项的选项行(我希望当你查看jsfiddler时这是有意义的)。当您单击行上children列上的查找链接时,我会在对话框中列出所有选项行并使用复选框列表,并允许用户选择与特定行的子关系,因此有多对多行之间的关系。
我在第一个选项组中默认了我想要的输出数据,但我不确定如何使其工作。
我不确定我是否会采用这种正确的方式,并希望一些Knockout大师可以指出我在弹出窗口中获得此功能的正确方向。
/*Select Options*/
var initialData = [{
title: "User Band",
productoptionrows: [{
id: "1",
title: "25-100",
related: [{
id: "4",
title: '1 Year'
}, {
id: "5",
title: '2 Year'
}, {
id: "6",
title: '3 Year'
}]
}, {
id: "2",
title: "101-250",
related: [{
id: "7",
title: '1 Year'
}, {
id: "8",
title: '2 Year'
}, {
id: "9",
title: 'qwe'
}]
}, {
id: "3",
title: "251-500",
related: [{
id: "10",
title: '1 Year'
}, {
id: "11",
title: '2 Year'
}, {
id: "12",
title: '3 Year'
}]
}]
}, {
title: "Please select the number of years license",
productoptionrows: [{
id: "4",
title: "1 Year",
related: []
}, {
id: "5",
title: "2 Year",
related: []
}, {
id: "6",
title: "3 Year",
related: []
}, {
id: "7",
title: "1 Year",
related: []
}, {
id: "8",
title: "2 Year",
related: []
}, {
id: "9",
title: "3 Year",
related: []
}, {
id: "10",
title: "1 Year",
related: []
}, {
id: "11",
title: "2 Year",
related: []
}, {
id: "12",
title: "3 Year",
related: []
}]
}];
$(document).ready(function () {
/*Models*/
var mappingOptions = {
'productoptionrows': {
create: function (options) {
return new productoptionrow(options.data);
}
}
};
var mappingOptionsPR = {
create: function (options) {
return new productoptionrow(options.data);
}
};
var productoptionrow = function (por) {
var self = ko.mapping.fromJS(por, {}, this);
self.relatedcsv = ko.computed(function () {
return $(por.related).map(function () {
return this.id;
}).get().join(',');
}, self);
self.selectedrelated = ko.observableArray($(por.related).map(function () {
return this.id;
}).get());
};
var ProductOptionModel = function (data) {
var self = this;
self.productoptions = ko.mapping.fromJS(data, mappingOptions);
self.isOpen = ko.observable(false);
self.selectedrelated = ko.observableArray([]);
/*Control Events*/
self.addProductOption = function () {
var newoption = ko.mapping.fromJS({
title: "Please select the number of years license",
productoptionrows: ko.observableArray([{
id: "15",
title: "25-100",
related: []
}, {
id: "16",
title: "101-250",
related: []
}, {
id: "17",
title: "251-500",
related: []
}])
}, mappingOptions);
self.productoptions.push(newoption);
};
self.copyProductOption = function (productoption) {
var copy = ko.mapping.fromJS(ko.mapping.toJS(productoption), mappingOptions);
self.productoptions.push(copy);
};
self.removeProductOption = function (productoption) {
self.productoptions.remove(productoption);
};
self.addProductOptionRow = function (productoption) {
var newrow = ko.mapping.fromJS({
id: "15",
title: "25-100",
related: []
}, mappingOptionsPR);
productoption.productoptionrows.push(newrow);
};
self.removeProductOptionRow = function (productoption) {
$.each(self.productoptions(), function () {
this.productoptionrows.remove(productoption)
})
};
self.open = function (productoption, event) {
self.selectedrelated(productoption.related);
self.isOpen(true);
};
self.close = function () {
self.isOpen(false);
}
self.associaterelated = function (record, elem) {
//console.log(ko.mapping.toJS(record));
}
};
ko.applyBindings(new ProductOptionModel(initialData), document.getElementById('page-wrapper'));
});

<link href="https://code.jquery.com/ui/1.12.1/themes/ui-lightness/jquery-ui.css" rel="stylesheet" />
<script src="https://code.jquery.com/jquery-2.2.4.min.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout.mapping/2.4.1/knockout.mapping.min.js"></script>
<script src="https://cdn.rawgit.com/gvas/knockout-jqueryui/075b303a/dist/knockout-jqueryui.min.js"></script>
<div id="page-wrapper">
<div>
<button title="Add Option" type="button" data-bind='click: $root.addProductOption'>Add Option</button>
</div>
<div id="options" data-bind="foreach: productoptions">
<div style="padding:10px;margin:20px;background-color:whitesmoke">
<table class="option-header" cellpadding="0" cellspacing="0">
<thead>
<tr>
<th>Group Title <span class="required">*</span></th>
<th>
<button title="Copy" type="button" class="" style="" data-bind='click: $root.copyProductOption'>Copy</button>
<button title="Delete Option" type="button" data-bind='click: $root.removeProductOption'>Delete Option</button>
</th>
</tr>
</thead>
<tbody>
<tr style="height:36px;">
<td>
<input type="text" data-bind='value: title'>
</td>
<td>
</td>
</tr>
</tbody>
</table>
<div>
<table class="option-header-rows" cellpadding="0" cellspacing="0">
<thead>
<tr class="headings">
<th>Id</th>
<th colspan="2" class="type-title">Title <span class="required">*</span></th>
<th>Children</th>
<th></th>
</tr>
</thead>
<tbody data-bind="foreach: productoptionrows">
<tr>
<td align="center">
<input required type="text" style="width:40px" data-bind='value: id'>
</td>
<td colspan="2">
<input type="text" value="25-100" data-bind='value: title'>
</td>
<td>
<input type="text" data-bind='value: relatedcsv' name="isdefault"><a href="#" data-bind="click: $root.open, disable: $root.isOpen">Lookup</a></td>
<td>
<button title="Delete Row" type="button" data-bind='click: $root.removeProductOptionRow'>Delete Row</button>
</td>
</tr>
</tbody>
<tfoot>
<tr>
<td align="right">
<button title="Add New Row" type="button" data-bind='click: $root.addProductOptionRow'>Add New Row</button>
</td>
</tr>
</tfoot>
</table>
</div>
</div>
</div>
<!-- popup -->
<div data-bind="dialog: { isOpen: isOpen,title:'Select relations', modal:true }">
<div data-bind="foreach: $root.productoptions">
<div data-bind='text: title'></div>
<div data-bind="foreach: productoptionrows">
<div>
<input type="checkbox" data-bind="value: id, checked: $root.selectedrelated" style="width:auto" />
ID <span data-bind='text: id'></span> - <span data-bind='text: title'></span>
</div>
</div>
</div>
</div>
<pre data-bind="text: ko.toJSON($data, null, 2)"></pre>
</div>
&#13;
答案 0 :(得分:0)
我试图将多对多问题提炼成一个简单的例子。在这里,人和事物彼此映射。为了跟踪映射,每个人都有一个列表。对于每个可能的东西,都有一个带有该值的复选框。它的checked
绑定绑定到当前人的thingList。
绑定到数组会使复选框插入或从数组中删除其值。
function person(name) {
return {
name,
thingList: ko.observableArray()
};
}
const vm = {
people: ko.observableArray(['Abby', 'Bill', 'Charlie'].map((n) => person(n))),
things: ko.observableArray(['apple', 'bullet', 'cup', 'doll', 'egg'])
};
ko.applyBindings(vm);
.checklist {
display: inline-block;
}
.no-bullets {
list-style-type: none;
}
.no-bullets li {
display: inline;
padding-right: 15px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
<div data-bind="foreach:people">
<div>Name: <span data-bind="text:name"></span>
<div class="checklist" data-bind="foreach:$parent.things">
<label><input type="checkbox" data-bind="value:$data, checked:$parent.thingList"><span data-bind="text:$data"></span></label>
</div>
<ul class="no-bullets" data-bind="foreach:thingList"><li data-bind="text:$data"></li></ul>
</div>
</div>