jsViews $.observable(arr).insert() 不触发 DOM 更新
jsViews $.observable(arr).insert() not triggering DOM update
我正在使用 $.observable(array).insert() 将项目附加到列表中。这正在更新我的视图,因为它应该:新列表项呈现给 DOM。但是,我想在新的 DOM 节点上发出一个点击事件(我依靠该事件添加一个 class 来扩展该项目并将另一个侦听器附加到主体,以便该区域可以关闭)。
我都试过了
$.observable(_model.leadTimes).insert(leadTime);
$leadTimes.find('.lead-time-data').last().find('.start-editing').click();
...和
function watchLeadTimes() {
var changeHandler = function (ev, eventArgs) {
if (eventArgs.change === 'insert') {
$leadTimes.find('.lead-time-data').last().find('.start-editing').click();
}
};
$.observe(_model.leadTimes, changeHandler);
}
而且它们都不起作用,但是,如果我将 jQuery 方法包装在 setTimout 中,例如 setTimeout(function () { $leadTimes.find('.lead-time-data').last().find('.start-editing').click(); }, 400);
,它 是否有效,让我相信这是一个时间问题,DOM 渲染在我的 jQuery click() 方法被调用之前不知何故没有完成。
既然你看到这个的可能性很大,Borris,感谢你的图书馆和你所做的一切!我认为 jsViews 是单一框架和普通旧 jQuery noodling 之间的绝佳中间地带!
编辑 2017 年 2 月 9 日
事实证明,我的问题是重叠的点击事件——我无意中处理了点击以在选择元素后立即取消选择它。然而,我借此机会重写了一些东西,以按照 Borris 的链接示例使用更具声明性的方法。
现在在我的模板中,我正在使用计算的可观察对象,isSelected
来切换 .editing class:
{^{for leadTimes}}
<tr class="lead-time-data" data-link="class{merge:~isSelected() toggle='editing'}">
<span>{^{:daysLead}}</span>
</tr>
{{/for}}
还有这个 JS:
function addNewLeadTimeClickHandler() {
var onNewLeadTimeClick = function () {
e.stopPropagation(); // this is what I was missing
var leadTime = {
daysLead: 1,
description: ''
};
$.observable(_model.activityMapping.leadTimes).insert(leadTime);
selectLeadtime(_model.activityMapping.leadTimes.length -1);
}
$leadTimes.on('click', '.add', onNewLeadTimeClick);
}
function selectLeadtime(index) {
var addStopEditingClickHandler = function () {
var onClickHandler = function (event) {
if ($(event.target).closest('tr').hasClass('editing')) {
setHandler();
return;
}
selectLeadtime(-1)
};
function setHandler() {
var clickEvent = 'click.ActivityChangeRequestDetailController-outside-edit-row';
$('html:not(.edit)').off(clickEvent).one(clickEvent, onClickHandler);
};
setHandler();
}
if (_model.selectedLeadtimeIndex !== index) {
$.observable(_model).setProperty('selectedLeadtimeIndex', index)
addStopEditingClickHandler();
}
}
function isSelected() {
var view = this;
return this.index === _model.selectedLeadtimeIndex;
}
// isSelected.depends = ["_model^selectedLeadtimeIndex"];
// for some reason I could not get the above .depends syntax to work
// ...or "_model.selectedLeadtimeIndex" or "_model.selectedLeadtimeIndex"
// but this worked ...
isSelected.depends = function() {return [_model, "selectedLeadtimeIndex"]};
observable insert()
方法是同步的。如果您的列表项仅使用 {^{for}}
呈现,那么这也是同步的,因此您不需要使用 setTimeout 或回调。 (有这样的回调可用,但您在这种情况下不需要它们。)
参见示例 http://www.jsviews.com/#samples/editable/tags (code here):
$.observable(movies).insert({...});
// Set selection on the added item
app.select($.view(".movies tr:last").index);
选择被同步添加到新插入的项目上。
您的渲染中是否还有其他异步代码?
顺便说一句,如果您使用委托模式,通常不需要向添加的元素添加新的点击处理程序。例如,在同一个示例中,用于删除电影的点击处理程序最初添加到容器 "#movieList"
中,并带有委托选择器 ".removeMovie"
(参见 code)。这甚至适用于稍后添加的电影。
相同的场景使用 {{on}}
见 http://www.jsviews.com/#link-events:"The selector argument can target elements that are added later"
我正在使用 $.observable(array).insert() 将项目附加到列表中。这正在更新我的视图,因为它应该:新列表项呈现给 DOM。但是,我想在新的 DOM 节点上发出一个点击事件(我依靠该事件添加一个 class 来扩展该项目并将另一个侦听器附加到主体,以便该区域可以关闭)。
我都试过了
$.observable(_model.leadTimes).insert(leadTime);
$leadTimes.find('.lead-time-data').last().find('.start-editing').click();
...和
function watchLeadTimes() {
var changeHandler = function (ev, eventArgs) {
if (eventArgs.change === 'insert') {
$leadTimes.find('.lead-time-data').last().find('.start-editing').click();
}
};
$.observe(_model.leadTimes, changeHandler);
}
而且它们都不起作用,但是,如果我将 jQuery 方法包装在 setTimout 中,例如 setTimeout(function () { $leadTimes.find('.lead-time-data').last().find('.start-editing').click(); }, 400);
,它 是否有效,让我相信这是一个时间问题,DOM 渲染在我的 jQuery click() 方法被调用之前不知何故没有完成。
既然你看到这个的可能性很大,Borris,感谢你的图书馆和你所做的一切!我认为 jsViews 是单一框架和普通旧 jQuery noodling 之间的绝佳中间地带!
编辑 2017 年 2 月 9 日
事实证明,我的问题是重叠的点击事件——我无意中处理了点击以在选择元素后立即取消选择它。然而,我借此机会重写了一些东西,以按照 Borris 的链接示例使用更具声明性的方法。
现在在我的模板中,我正在使用计算的可观察对象,isSelected
来切换 .editing class:
{^{for leadTimes}}
<tr class="lead-time-data" data-link="class{merge:~isSelected() toggle='editing'}">
<span>{^{:daysLead}}</span>
</tr>
{{/for}}
还有这个 JS:
function addNewLeadTimeClickHandler() {
var onNewLeadTimeClick = function () {
e.stopPropagation(); // this is what I was missing
var leadTime = {
daysLead: 1,
description: ''
};
$.observable(_model.activityMapping.leadTimes).insert(leadTime);
selectLeadtime(_model.activityMapping.leadTimes.length -1);
}
$leadTimes.on('click', '.add', onNewLeadTimeClick);
}
function selectLeadtime(index) {
var addStopEditingClickHandler = function () {
var onClickHandler = function (event) {
if ($(event.target).closest('tr').hasClass('editing')) {
setHandler();
return;
}
selectLeadtime(-1)
};
function setHandler() {
var clickEvent = 'click.ActivityChangeRequestDetailController-outside-edit-row';
$('html:not(.edit)').off(clickEvent).one(clickEvent, onClickHandler);
};
setHandler();
}
if (_model.selectedLeadtimeIndex !== index) {
$.observable(_model).setProperty('selectedLeadtimeIndex', index)
addStopEditingClickHandler();
}
}
function isSelected() {
var view = this;
return this.index === _model.selectedLeadtimeIndex;
}
// isSelected.depends = ["_model^selectedLeadtimeIndex"];
// for some reason I could not get the above .depends syntax to work
// ...or "_model.selectedLeadtimeIndex" or "_model.selectedLeadtimeIndex"
// but this worked ...
isSelected.depends = function() {return [_model, "selectedLeadtimeIndex"]};
observable insert()
方法是同步的。如果您的列表项仅使用 {^{for}}
呈现,那么这也是同步的,因此您不需要使用 setTimeout 或回调。 (有这样的回调可用,但您在这种情况下不需要它们。)
参见示例 http://www.jsviews.com/#samples/editable/tags (code here):
$.observable(movies).insert({...});
// Set selection on the added item
app.select($.view(".movies tr:last").index);
选择被同步添加到新插入的项目上。
您的渲染中是否还有其他异步代码?
顺便说一句,如果您使用委托模式,通常不需要向添加的元素添加新的点击处理程序。例如,在同一个示例中,用于删除电影的点击处理程序最初添加到容器 "#movieList"
中,并带有委托选择器 ".removeMovie"
(参见 code)。这甚至适用于稍后添加的电影。
相同的场景使用 {{on}}
见 http://www.jsviews.com/#link-events:"The selector argument can target elements that are added later"