Ich habe ein verschachteltes Array von Gruppenproduktoptionen in einem Raster. Ich würde gerne einen Popup-Editor haben, der alle Produkte (productoptionrows) jeder gruppierten Produktoption auflistet und es einem Benutzer erlaubt, die Beziehungen zwischen ihnen zu überprüfen. Ich bin auf Beispiele von vielen zu vielen Beziehungen gestoßen, habe aber kein Beispiel für eine Selbstreferenz gesehen, die viele zu viele gruppiert hat.Knockoutjs - Verschachteltes Gruppen-Array mit Selbstreferenzierung von vielen zu vielen Kontrollkästchen-Liste
ich die folgenden Array-Datenstruktur:
[{
grouptitle: "User Band",
productoptionrows: [{
id: "1",
producttitle: "25-100",
relatedproductoptionrows: [{
id: "4",
title: '1 Year'
}, {
id: "5",
title: '2 Year'
}, {
id: "6",
title: '3 Year'
}]
}]
Ein Benutzer in der Lage sein wird, Gruppen mit einem Titel zu definieren, und eine Liste von Produkten zu dieser Gruppe hinzu. Sobald der Benutzer alle Gruppen und zugehörigen Produkte hinzugefügt hat, könnte der Benutzer auf eine Popup-Schaltfläche ("Suche") klicken, um die Beziehungen zwischen den Produkten jeder Gruppe zu überprüfen.
Das Problem, das ich habe, ist, in dem Popup mit, wenn Sie auf „Lookup“ für jedes Produkt Option klicken, ihre Beziehungen zu setzen und auch die Popup-Standard, so dass sie die Beziehungen bereits geprüft. Ich denke, die Wurzel zu meinem Problem ist im Versuch, mehrere verschachtelte Arrays zu kombinieren, aber ich bin nicht sicher, wie das Ansichtsmodell/die Daten zu strukturieren, um mit dieser Logik umzugehen.
Ich habe ein Fiedler gegründet unter dem unten mein Problem zeigen:
/*Select Options*/
var initialData = [{
grouptitle: "User Band",
productoptionrows: [{
id: "1",
producttitle: "25-100",
relatedproductoptionrows: [{
id: "4",
producttitle: '1 Year'
}, {
id: "5",
producttitle: '2 Year'
}, {
id: "6",
producttitle: '3 Year'
}]
}, {
id: "2",
producttitle: "101-250",
relatedproductoptionrows: [{
id: "7",
producttitle: '1 Year'
}, {
id: "8",
producttitle: '2 Year'
}, {
id: "9",
producttitle: '3 Year'
}]
}, {
id: "3",
producttitle: "251-500",
relatedproductoptionrows: [{
id: "10",
producttitle: '1 Year'
}, {
id: "11",
producttitle: '2 Year'
}, {
id: "12",
producttitle: '3 Year'
}]
}]
}, {
grouptitle: "Please select the number of years license",
productoptionrows: [{
id: "4",
producttitle: "1 Year",
relatedproductoptionrows: []
}, {
id: "5",
producttitle: "2 Year",
relatedproductoptionrows: []
}, {
id: "6",
producttitle: "3 Year",
relatedproductoptionrows: []
}, {
id: "7",
producttitle: "1 Year",
relatedproductoptionrows: []
}, {
id: "8",
producttitle: "2 Year",
relatedproductoptionrows: []
}, {
id: "9",
producttitle: "3 Year",
relatedproductoptionrows: []
}, {
id: "10",
producttitle: "1 Year",
relatedproductoptionrows: []
}, {
id: "11",
producttitle: "2 Year",
relatedproductoptionrows: []
}, {
id: "12",
producttitle: "3 Year",
relatedproductoptionrows: []
}]
}];
$(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.relatedproductoptionrowscsv = ko.computed(function() {
return $(por.relatedproductoptionrows).map(function() {
return this.id;
}).get().join(',');
}, self);
self.selectedrelatedproductoptionrows = ko.observableArray($(por.relatedproductoptionrows).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.selectedrelatedproductoptionrows = ko.observableArray([]);
/*Control Events*/
self.addProductOption = function() {
var newoption = ko.mapping.fromJS({
grouptitle: "Please select the number of years license",
productoptionrows: ko.observableArray([{
id: "15",
producttitle: "25-100",
relatedproductoptionrows: []
}, {
id: "16",
producttitle: "101-250",
relatedproductoptionrows: []
}, {
id: "17",
producttitle: "251-500",
relatedproductoptionrows: []
}])
}, 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",
producttitle: "25-100",
relatedproductoptionrows: []
}, mappingOptionsPR);
productoption.productoptionrows.push(newrow);
};
self.removeProductOptionRow = function (productoption) {
$.each(self.productoptions(), function() {
this.productoptionrows.remove(productoption)
})
};
self.open = function (productoption, event) {
self.selectedrelatedproductoptionrows(productoption.relatedproductoptionrows);
self.isOpen(true);
};
self.close = function() {
self.isOpen(false);
}
};
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 Group Option" type="button" data-bind='click: $root.addProductOption'>Add Group 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 Group</button>
<button title="Delete Option" type="button" data-bind='click: $root.removeProductOption'>Delete Group Option</button>
</th>
</tr>
</thead>
<tbody>
<tr style="height:36px;">
<td>
<input type="text" data-bind='value: grouptitle'>
</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">Product Title <span class="required">*</span></th>
<th>Related Ids</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: producttitle'>
</td>
<td>
<input type="text" data-bind='value: relatedproductoptionrowscsv' 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: grouptitle'></div>
<div data-bind="foreach: productoptionrows">
<div>
<input type="checkbox" data-bind="value:id, checkedValue: selectedrelatedproductoptionrows" style="width:auto" />
ID <span data-bind='text: id'></span> - <span data-bind='text: producttitle'></span>
</div>
</div>
</div>
</div>
<pre data-bind="text: ko.toJSON($data, null, 2)"></pre>
</div>
ich wirklich bin der Hoffnung, jemand verstehen kann, was im Versuch, diese Funktion zu erreichen und zu erhalten, wie ich Seit ein paar Tagen war ich dabei. Vielen Dank im Voraus