我有一个带有关联按钮的div,可以切换divs contenteditable true和false。
一旦编辑了div并且用户点击了保存,我就抓住内部html并将其存储在流星中,如下所示:
Template.note.events
'click #deleteNote': (e) ->
currentNoteId = @_id
Notes.remove currentNoteId, (error) ->
if error
Errors.throw('could not delete this note, contact support', false)
'click #editNote': (e, t) ->
note = t.find '.note-container'
classie.toggle t.find('.note'), 'focus'
if t.$('.note').hasClass 'focus'
$(e.target).text 'Save'
editor.activate()
else
$(e.target).attr 'disabled'
currentNoteId = @_id
console.log note.innerHTML
Notes.update currentNoteId,
$set:
html: note.innerHTML
, (error) ->
if error
console.log error
editor.deactivate()
$(e.target).text 'Edit'
$(e.target).removeAttr 'disabled'
我注意到一个奇怪的错误。我知道这是由于Meteors的反应性,因为如果我在notes集合上禁用更新命令,则不会发生这种情况。
如果我编辑最后一行文本,或在内容末尾添加新行,Meteor会自动更新div,最后一行重复两次。但是,如果我刷新页面,则正确的内容会显示在注释中。
因此数据在数据库中是最新的,但由于反应性而在屏幕上呈现的内容并不反映数据库中的内容。这是meteor如何更新页面的错误。对此有何解决方案?如果您需要更多信息,或者如果您发现我的解释令人困惑,请告诉我。
更新
因此,如果我禁用反应性并使用服务器返回数据手动呈现模板并附加到DOM,则可以正常工作。所以这绝对是Meteor的反应性如何与可信的div一起工作的一个错误。
使用手动插入更新代码:
Template.note.events
'click #deleteNote': (e, t) ->
e.preventDefault()
currentNoteId = @_id
Notes.remove currentNoteId, (error) ->
if error
Errors.throw('could not delete this note, contact support', false)
else
t.__component__.dom.remove()
return false
'click #editNote': (e, t) ->
note = t.find '.note-container'
classie.toggle t.find('.note'), 'focus'
if t.$('.note').hasClass 'focus'
$(e.target).text 'Save'
editor.activate()
else
$(e.target).attr 'disabled'
currentNoteId = @_id
console.log note.innerHTML
Notes.update currentNoteId,
$set:
html: note.innerHTML
, (error) ->
if error
console.log error
Errors.throw('could not save this note, contact support', false)
editor.deactivate()
$(e.target).text 'Edit'
$(e.target).removeAttr 'disabled'
更新2
经过更多的测试,我已经接近理解这个问题了。问题在于Meteor反应性地更新已经由用户使用contenteditable特征更新的div内容。
因此用户编辑div的内容,当用户完成并单击“保存”时,我抓取内容并将其保存到数据库中。 div并不真正需要更新,因为用户已经更新了它并且我正在存储结果。但由于流星的反应性,它认为它需要更新div,并且它不正确。
所以问题在于Meteor反应性地更新已经准确的DOM元素,因为更新是基于用户使用contenteditable功能编辑的内容。
答案 0 :(得分:1)
请参阅此问题:https://github.com/meteor/meteor/issues/2328#issuecomment-49833061
看起来Meteor可能不对此更新负责。所以我们必须自己保存和更新插入符号。
"在保存可信内容并将其存储在数据库中时,您可以获得carret的位置。稍后您可以阅读此位置并将插入符号移动到适当的位置。您在Google Docs这样的应用程序中也有类似的情况,它们会保留每个用户的插入位置并相应地显示它。"
我在网上找到了最好的插入包以保存和更新插入位置,Rangy:
https://code.google.com/p/rangy/wiki/SelectionSaveRestoreModule
真的很棒。我只保存插入符号位置然后更新文档并在回调中恢复插入符号。
答案 1 :(得分:1)
知道这个问题已经过了一年多了但是我在这里试图绕过这个问题。
使用铁路由器
Router.route('/myroute', {
waitOn: function(){
return [Meteor.subscribe('collection', {data:params})];
},
action: {
var myObject = Collection.findOne();
this.render('myTemplate', {
data: function(){
return myObject;
}
});
}
};
Le 模板
<template name="panel-description">
<b>Description</b>
<div contenteditable data-name="description" class="can-edit">{{{ getDescription }}}</div>
</template>
辅助
Template.objectInfo.helpers({
'getDescription': function(){
if(typeof this.description !== 'undefined' && this.description !== null){
return this.description;
}
else{
return 'N/A';
}
},
});
模糊/焦点事件和相应的方法调用
Template.objectInfo.events({
'focus .can-edit' : function(e){
// Get the description of myObject in currentData() so we can later compare for changes
e.currentTarget.setAttribute('data-content', Template.currentData().description);
},
'blur .can-edit' : function(e){
// Afer blur, store the content of our element
var newData = e.currentTarget.innerHTML;
// Compare if new content is diferent than previous one we stored in data-content
// attribute. Only make the server call if data changes.
if(e.currentTarget.getAttribute('data-content') != newData){
// Clear the element
e.currentTarget.innerHTML = '';
// The call to update our DB field.
Meteor.call('saveObjectDescription', Template.currentData()._id, newData, function(err){
// callback for error/success feedback
});
};
},
});
有点hacky,但是诀窍。
路由执行后, getDescription 帮助程序返回 myObject 的描述。在模糊时,我们检查先前内容的变化(存储在具有焦点事件的属性中),如果存在差异,则调用更新方法。
Meteor将立即通过帮助程序返回值,但为了避免重复的内容问题,我们在调用之前清理元素。
当HTML为空时,闪烁一微秒的元素有点粗糙,除此之外,它还可以工作。
PS:使用三重括号将帮助器呈现为HTML。
希望有所帮助。
答案 2 :(得分:0)
这可能很有用:https://github.com/meteor/meteor/issues/1964#issuecomment-57948734
解决了我的问题,当在Helper变量之前输入了ny用户的文本。