我的观察结果发生变化之后,我遇到了丢失UI状态变化的问题,并希望得到一些建议。
首先,我轮询我的服务器以获取更新。这些消息在我的视图模型中,并且< ul>完美呈现:
当我的用户点击"回复"或者"分配给"按钮,我显示一个小表格来执行这些操作:
我现在的问题是,当我的下一个轮询调用返回时,列表会重新绑定,并且我将丢失表单应该打开的状态。我为" currentQuestionID"添加了视图模型属性。所以我可以使用visible:binding并在绑定后重新显示表单。
完成后,表格会正确显示在"当前项目"重新绑定后,但表单值丢失。也就是说,它重新绑定,重建表单元素,显示它们,但任何用户输入都会消失(这当然是有意义的,因为HTML刚刚重新生成)。
我试图遵循相同的模式(使用值:绑定来设置值和事件:{change:responseChanged}绑定以使用值更新observable)。 HTML片段如下所示:
<form action="#" class="tb-reply-form" data-bind="visible: $root.showMenu($data, 'reply')">
<textarea id="tb-response" data-bind="value: $root.currentResponse, event: {keyup: $root.responseChanged}"></textarea>
<input type="button" id="tb-submitResponse" data-bind="click: $root.submitResponse, clickBubble: false" value="Send" />
</form>
<form action="#" class="tb-assign-form" data-bind="visible: $root.showMenu($data, 'assign')">
<select id="tb-assign" class="tb-assign" data-bind="value: $root.currentAssignee, options: $root.mediators, optionsText: 'full_name', optionsValue: 'access_token', optionsCaption: 'Select one...', event: {change: $root.assigneeChanged}">
</select>
<input type="button" id="tb-submitAssignment" data-bind="click: $root.submitAssignment, clickBubble: false" value="Assign"/>
</form>
现在,我最终看起来像一个无限循环,其中设置值会导致更改发生,从而导致值......等等。
我想&#34;搞砸了#34;只需将其移出foreach ...通过移动每个&lt; li&gt;之外的表单。在foreach中:绑定并进行一些DOM操作以将表单移动到&#34;当前项目&#34;,我认为我不会丢失用户输入。
replyForm.appendTo(theContainer).show();
直到第一次轮回返回&amp;重新绑定。由于HTML是为&lt; ul&gt;重新生成的,因此DOM不再具有我的表单,我尝试抓取它并执行.appendTo(容器)不会做任何事情。我想在这里,我可以将元素复制到活动项而不是移动它?
所以,这一切似乎都让我错过了一些基本的东西,因为有人必须在淘汰赛中将表格放入foreach循环中!
是否有人有策略在敲除中的绑定项目内维护表单状态?
或者,可能有一种方法可以让淘汰赛没有绑定任何已经绑定的东西,只会产生新的&#34;元件。
最后,我应该为此废弃淘汰赛并手动生成&#34;新物品&#34;每次轮询电话回来时我自己。
最后一点信息;如果我将我的轮询间隔设置为30秒,所有位&#34;工作&#34;因为它提交,保存,重新绑定等等。我只需要表格及其内容通过重新绑定来实现。
非常感谢您的帮助!
答案 0 :(得分:1)
好吧,我自己想出来了。而且令人尴尬。
以下是我的VM代码的一部分:
function TalkbackViewModel( id ) {
var self = this;
talkback.state.currentTalkbackId = "";
talkback.state.currentAction = "";
talkback.state.currentResponse = "";
talkback.state.currentAssignee = "";
self.talkbackQueue = ko.observableArray([]);
self.completeQueue = ko.observableArray([]);
self.mediators = ko.observableArray([]);
self.currentTalkbackId = ko.observable(talkback.state.currentTalkbackId);
self.currentAction = ko.observable(talkback.state.currentAction);
self.currentResponse = ko.observable(talkback.state.currentResponse);
self.currentAssignee = ko.observable(talkback.state.currentAssignee);
self.showActionForm = function(data, action) {
return ko.computed(function() {
var sameAction = (self.currentAction() == action);
var sameItem = (self.currentTalkbackId() == data.talkback_id());
return (sameAction && sameItem);
}, this);
};
self.replyToggle = function(model, event) {
// we're switching from one item to another. clear input values.
if (self.currentTalkbackId() != model.talkback_id() || self.currentAction() != "reply") {
self.currentResponse("");
self.currentAssignee("");
self.currentTalkbackId(model.talkback_id());
}
我的第一个错误是试图对待textarea&amp;下拉一样。我注意到下拉列表是节省价值&amp;重新加载,但愚蠢地试图保持代码与textarea相同,并引起我自己的问题。
因此...
首先,我回到使用currentAssignee和currentResponse的$ root视图模型属性来关闭值并使用value:bindings重新绑定这些控件。
接下来,我需要删除事件处理程序:
event: { change: xxxChanged }
因为它们没有意义(双向绑定!!!!)。下拉值使用值:binding。
自动更改和更新textarea只更新了模糊,导致我认为我需要onkeyup,onkeydown等。我摆脱了那些处理程序,因为它们1)错误,2)搞砸了值:绑定创建一个无限循环。
我只在textarea上需要这个以获取我的viewmodel属性的最新值更新:
valueUpdate: 'input'
在这一点上,一切都得以挽回重新绑定,我没有失去我的价值观,但我的插入位置在textarea中是不正确的。我添加了一些代码来处理:
var item = element.find(".tb-assign");
var oldValue = item.val();
item.val('');
item.focus().val(oldValue);
如果您只是执行item.focus()。某些浏览器的行为正常.val(item.val());但我需要实际上使价值变为&#34;改变&#34;在我的情况下,最后得到插入符号,所以我保存了值,清除它,然后恢复它。我在事件处理程序中执行了此操作,以便将事件数据返回到浏览器:
$(window).on("talkback.retrieved", function(event, talkback_queue, complete_queue) {
var open_mappings = ko.mapping.fromJS(talkback_queue);
self.talkbackQueue(open_mappings);
if (talkback_queue) self.queueLength(talkback_queue.length);
var completed_mappings = ko.mapping.fromJS(complete_queue);
self.completeQueue(completed_mappings);
if (self.currentTalkbackId()) {
var element = $("li[talkbackId='" + self.currentTalkbackId() + "']");
if (talkback.state.currentAction == "assign") {
var item = element.find(".tb-assign");
var oldValue = item.val();
item.val('');
item.focus().val(oldValue);
} else {
var item = element.find(".tb-response");
var oldValue = item.val();
item.val('');
item.focus().val(oldValue);
}
}
}
);
所以,我的最后一个问题是,如果我在我的方法中使用了我的observable&#34;清除&#34;当一个新的&#34;当前项目&#34;被选中(replyToggle&amp; assignToggle),它们似乎不起作用。
self.currentResponse("");
self.currentAssignee("");
我无法清除值。我不得不做一些hack-fu并在下面添加一行来解决它现在:
$(".tb-assign").val("");