JSViews 可观察数组在删除/添加和排序时不刷新视图
JSViews observable arrays are not refreshing the view on removed / adding and sorting
我正在尝试将项目从一个数组移动到另一个数组,并按名称对它们进行排序。
这部分工作正常,似乎 observable.refresh 更新了数据本身,但视图仍然显示旧数据,使用 moveFromTo() 将移动项目,但不会更新它们在视图中的顺序。
moveFromToType2() 将显示添加的项目,但不会更新从中删除的项目。
在这两种情况下,执行 view.refresh() 都可以解决问题,但我认为这不是预期的行为。
https://jsfiddle.net/y946xhvq/
<body>
<div id="multiselect"></div>
<script id="multiselectTemplate" type="text/x-jsrender">
<select id="leftSelect" multiple>
{^{for left}}
<option data-link="value{:#index}">{^{:name}}</option>
{{/for}}
</select>
<button id="rightButton"> > </button>
<button id="leftButton"> < </button>
<select id="rightSelect" multiple>
{^{for right}}
<option data-link="value{:#index}">{^{:name}}</option>
{{/for}}
</select>
</script>
<script>
var data = {
left: [{ "id": 0, "name": "Melendez Garner" }, { "id": 1, "name": "Mara Orr" }, { "id": 2, "name": "Bass Salazar" }, { "id": 3, "name": "Carol Freeman" }, { "id": 4, "name": "Selma Bradford" }, { "id": 5, "name": "Cotton Parrish" }, { "id": 6, "name": "Haley Campbell" }, { "id": 7, "name": "Ruth Wright" }, { "id": 8, "name": "Carmella Blake" }],
right: []
}
data.left.sort((a, b) => a.name.localeCompare(b.name));
var m = $.templates('#multiselectTemplate').link('#multiselect', data);
$('#multiselect').on('click', '#leftButton', function () {
//MOVE FROM RIGHT TO LEFT
var view = $.view(this);
var value = $('#rightSelect').val();
if (value === null) return;
//moveFromToType2(data.right, data.left, value);
moveFromTo(data.right, data.left, value);
//view.refresh();
}).on('click', '#rightButton', function () {
//MOVE FROM LEFT TO RIGHT
var view = $.view(this);
var value = $('#leftSelect').val();
if (value === null) return;
//moveFromToType2(data.left, data.right, value);
moveFromTo(data.left, data.right, value);
//view.refresh();
})
function moveFromToType2(from, to, index) {
if (from.length == 0) return;
if (index !== undefined) {
let selected = index.map(d => from[d]);
selected.forEach(d => {
let i = from.indexOf(d);
from.splice(i, 1);
});
$.observable(to).insert(selected);
to.sort((a, b) => a.name.localeCompare(b.name));
from.sort((a, b) => a.name.localeCompare(b.name));
}
}
function moveFromTo(from, to, index) {
if (from.length == 0) return;
if (index !== undefined) {
let selected = index.map(d => from[d]);
selected.forEach(d => {
let i = from.indexOf(d);
$.observable(from).remove(i);
});
$.observable(to).insert(selected);
to.sort((a, b) => a.name.localeCompare(b.name));
from.sort((a, b) => a.name.localeCompare(b.name));
$.observable(to).refresh(to);
$.observable(from).refresh(from);
}
}
</script>
这里的问题是您正在对 to
和 from
进行不可观察的更改和可观察的更改。如果您希望 UI 在数据链接的驱动下正确更新,您只需对这些数组进行可观察到的更改。
这是一个纠正这个问题的版本,首先克隆每个数组,然后对克隆进行不可观察的更改,然后最后将克隆传递给 refresh()
,以进行可观察的更新(合并所有变化):
https://jsfiddle.net/BorisMoore/qsvhm4x6/4/
function moveFromTo(from, to, index) {
if (from.length == 0) return;
let newFrom = from.slice(0); // Make a clone of from array
if (index !== undefined) {
let selected = index.map(d => newFrom[d]);
selected.forEach(d => {
let i = newFrom.indexOf(d);
newFrom.splice(i, 1); // Remove selected objects from clone
});
let newTo = to.concat(selected); // Make a clone of to array, plus selected objects
newTo.sort((a, b) => a.name.localeCompare(b.name)); // Sort
newFrom.sort((a, b) => a.name.localeCompare(b.name)); // Sort
$.observable(to).refresh(newTo); // Now observably update 'to', to the new array
$.observable(from).refresh(newFrom); // Now observably update 'from', the new array
}
}
这是一种不同的方法,在 {^{for}}
上使用内置的 sort feature,而不是对基础数据进行排序。它还在 <select>
元素上使用数据链接:
https://jsfiddle.net/BorisMoore/f70pnkwa/11/
<select id="leftSelect" multiple size="10" data-link="leftSelect">
{^{for left sort="name"}}
<option data-link="value{:id} {:name}"></option>
{{/for}}
</select>
我正在尝试将项目从一个数组移动到另一个数组,并按名称对它们进行排序。
这部分工作正常,似乎 observable.refresh 更新了数据本身,但视图仍然显示旧数据,使用 moveFromTo() 将移动项目,但不会更新它们在视图中的顺序。
moveFromToType2() 将显示添加的项目,但不会更新从中删除的项目。
在这两种情况下,执行 view.refresh() 都可以解决问题,但我认为这不是预期的行为。
https://jsfiddle.net/y946xhvq/
<body>
<div id="multiselect"></div>
<script id="multiselectTemplate" type="text/x-jsrender">
<select id="leftSelect" multiple>
{^{for left}}
<option data-link="value{:#index}">{^{:name}}</option>
{{/for}}
</select>
<button id="rightButton"> > </button>
<button id="leftButton"> < </button>
<select id="rightSelect" multiple>
{^{for right}}
<option data-link="value{:#index}">{^{:name}}</option>
{{/for}}
</select>
</script>
<script>
var data = {
left: [{ "id": 0, "name": "Melendez Garner" }, { "id": 1, "name": "Mara Orr" }, { "id": 2, "name": "Bass Salazar" }, { "id": 3, "name": "Carol Freeman" }, { "id": 4, "name": "Selma Bradford" }, { "id": 5, "name": "Cotton Parrish" }, { "id": 6, "name": "Haley Campbell" }, { "id": 7, "name": "Ruth Wright" }, { "id": 8, "name": "Carmella Blake" }],
right: []
}
data.left.sort((a, b) => a.name.localeCompare(b.name));
var m = $.templates('#multiselectTemplate').link('#multiselect', data);
$('#multiselect').on('click', '#leftButton', function () {
//MOVE FROM RIGHT TO LEFT
var view = $.view(this);
var value = $('#rightSelect').val();
if (value === null) return;
//moveFromToType2(data.right, data.left, value);
moveFromTo(data.right, data.left, value);
//view.refresh();
}).on('click', '#rightButton', function () {
//MOVE FROM LEFT TO RIGHT
var view = $.view(this);
var value = $('#leftSelect').val();
if (value === null) return;
//moveFromToType2(data.left, data.right, value);
moveFromTo(data.left, data.right, value);
//view.refresh();
})
function moveFromToType2(from, to, index) {
if (from.length == 0) return;
if (index !== undefined) {
let selected = index.map(d => from[d]);
selected.forEach(d => {
let i = from.indexOf(d);
from.splice(i, 1);
});
$.observable(to).insert(selected);
to.sort((a, b) => a.name.localeCompare(b.name));
from.sort((a, b) => a.name.localeCompare(b.name));
}
}
function moveFromTo(from, to, index) {
if (from.length == 0) return;
if (index !== undefined) {
let selected = index.map(d => from[d]);
selected.forEach(d => {
let i = from.indexOf(d);
$.observable(from).remove(i);
});
$.observable(to).insert(selected);
to.sort((a, b) => a.name.localeCompare(b.name));
from.sort((a, b) => a.name.localeCompare(b.name));
$.observable(to).refresh(to);
$.observable(from).refresh(from);
}
}
</script>
这里的问题是您正在对 to
和 from
进行不可观察的更改和可观察的更改。如果您希望 UI 在数据链接的驱动下正确更新,您只需对这些数组进行可观察到的更改。
这是一个纠正这个问题的版本,首先克隆每个数组,然后对克隆进行不可观察的更改,然后最后将克隆传递给 refresh()
,以进行可观察的更新(合并所有变化):
https://jsfiddle.net/BorisMoore/qsvhm4x6/4/
function moveFromTo(from, to, index) {
if (from.length == 0) return;
let newFrom = from.slice(0); // Make a clone of from array
if (index !== undefined) {
let selected = index.map(d => newFrom[d]);
selected.forEach(d => {
let i = newFrom.indexOf(d);
newFrom.splice(i, 1); // Remove selected objects from clone
});
let newTo = to.concat(selected); // Make a clone of to array, plus selected objects
newTo.sort((a, b) => a.name.localeCompare(b.name)); // Sort
newFrom.sort((a, b) => a.name.localeCompare(b.name)); // Sort
$.observable(to).refresh(newTo); // Now observably update 'to', to the new array
$.observable(from).refresh(newFrom); // Now observably update 'from', the new array
}
}
这是一种不同的方法,在 {^{for}}
上使用内置的 sort feature,而不是对基础数据进行排序。它还在 <select>
元素上使用数据链接:
https://jsfiddle.net/BorisMoore/f70pnkwa/11/
<select id="leftSelect" multiple size="10" data-link="leftSelect">
{^{for left sort="name"}}
<option data-link="value{:id} {:name}"></option>
{{/for}}
</select>