我是Knockout的新手,我已经成功地从数据源创建了一个记录表。我需要在表的每一行中添加一个带有两个选项“ Primary”和“ Secondary”的下拉列表。我需要从表中的其他项目中删除所选的选项。例如,如果表中的第一行选择了“主要”,则无需允许其他行再次选择它。我的行数未知。
答案 0 :(得分:1)
要实现此功能,您的各个行需要访问其他行以检查正在使用的值。在实现此功能之前,让我们先编写一个朴素的示例,以便我们知道我们正在使用什么。
如果您运行以下代码段,则会看到常规UI 没有描述的功能。
在问有关Stackoverflow的问题时,您通常会自己提供这些示例,因此人们有一个很好的起点来帮助您解决问题!但是,由于您是新的参与者,因此此人就在我身上。
function Row(id) {
this.name = id;
this.selectedSource = ko.observable(null);
this.sourceOptions = [ "Primary", "Secondary" ]
};
function App() {
this.rows = ko.observableArray([]);
let lastRowId = 0;
this.addRow = () => {
this.rows.push(
new Row(lastRowId++)
);
}
};
const app = new App();
ko.applyBindings(app);
app.addRow();
app.addRow();
app.addRow();
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
<table data-bind="foreach: rows">
<tr>
<td data-bind="text: name"></td>
<td>
<select data-bind="value: selectedSource,
options: sourceOptions,
enable: sourceOptions.length,
optionsCaption: 'select source'">
</select>
</td>
</tr>
</table>
<button data-bind="click: addRow">add row</button>
以上示例假定sourceOptions
的静态列表。但是实际上,它是一个计算列表:
要实现此功能,我们首先需要访问其他行:
/* Row accepts a reference to its siblings (including itself) */
function Row(is, allRows) { /* ... */}
/* App passes a reference to all rows when constructing new ones */
new Row(0, this.rows);
现在我们可以访问其他行了,我们可以检查它们的选择并将其从可用选项列表中删除:
// Remove this row from the list
const otherRows = ko.pureComputed(() =>
allRows().filter(row => row !== this)
);
// Create a Set of all selections
const otherSelections = ko.pureComputed(() =>
new Set(otherRows().map(row => row.selectedSource()))
);
// Take the Base list and remove any element that is in otherSelections
this.sourceOptions = ko.pureComputed(() =>
[ "Primary", "Secondary" ]
.filter(s => !otherSelections().has(s))
);
查看下面的可运行代码段,以查看其运行情况。我还添加了一个enable
绑定以指示何时没有可供选择的选项!
如果事情仍然不清楚,请发表评论。我很乐意提供帮助。
function Row(id, allRows) {
this.name = id;
this.selectedSource = ko.observable(null);
const otherRows = ko.pureComputed(() =>
allRows().filter(row => row !== this)
);
const otherSelections = ko.pureComputed(() =>
new Set(otherRows().map(row => row.selectedSource()))
);
this.sourceOptions = ko.pureComputed(() =>
[ "Primary", "Secondary" ]
.filter(s => !otherSelections().has(s))
);
};
function App() {
this.rows = ko.observableArray([]);
let lastRowId = 0;
this.addRow = () => {
this.rows.push(
new Row(lastRowId++, this.rows)
);
}
};
const app = new App();
ko.applyBindings(app);
app.addRow();
app.addRow();
app.addRow();
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
<table data-bind="foreach: rows">
<tr>
<td data-bind="text: name"></td>
<td>
<select data-bind="value: selectedSource,
options: sourceOptions,
enable: sourceOptions().length,
optionsCaption: 'select source'">
</select>
</td>
</tr>
</table>
<button data-bind="click: addRow">add row</button>