2014-07-20 24 views
1

我有一個關聯的按鈕切換div contenteditable true和false的div。關於contenteditable div的流星反應有一個問題,我該如何解決?

enter image description here

一旦格已被編輯和用戶點擊保存我搶內部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集合上的更新命令,這不會發生。

如果我編輯文本的最後一行,或者在內容的末尾添加一行,流星會自動更新div,最後一行重複兩次。但是,如果我刷新頁面,正確的內容會顯示在註釋中。

因此,數據在數據庫中是最新的,但是由於反應而呈現在屏幕上的內容並不能反映數據庫中的內容。這是流星更新頁面的錯誤。任何解決方案?請讓我知道你是否需要更多信息,或者如果你發現我的解釋混亂。

UPDATE

所以,如果我禁用的反應性和手動渲染服務器返回數據的模板,並追加到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功能更新的divs內容。

因此,用戶編輯div的內容,當用戶完成並單擊保存時,我抓取內容並將其保存到數據庫。該div並不需要更新,因爲用戶已經更新了它並且我正在存儲結果。但是由於流星的反應性,它認爲它需要更新div,而且它不正確。

所以問題在於Meteor反應性地更新已準確的DOM元素,因爲更新是基於用戶使用contenteditable功能編輯的內容。

+0

你正在運行什麼版本的流星? –

+0

我正在運行的版本0.8.2 – nearpoint

+0

我發現這是Meteor處理contenteditable divs反應的方式的一個問題。在這裏查看github問題:https://github.com/meteor/meteor/issues/1964 – nearpoint

回答

1

看到這個問題:https://github.com/meteor/meteor/issues/2328#issuecomment-49833061

看起來像流星可能不是負責此更新。所以我們必須自己保存和更新插入符號。

「保存內容並將其存儲在數據庫中時,您可以獲得最佳位置,稍後您可以閱讀此位置並將其移動到適當的位置,您在Google Docs等應用程序中也有類似的情況,每個用戶的位置並相應顯示。「

我找到了最好的插入符包在網絡上保存和更新的插入位置,瘦長:

https://code.google.com/p/rangy/wiki/SelectionSaveRestoreModule

這真是偉大工程,我只保存然後插入位置更新的文件,在回調恢復插入符

+0

是否有工作流星包? –

1

知道這個問題已經過去了一年多了,但這是我試圖繞過這個問題。

使用鐵 - 路由器

Router.route('/myroute', { 
    waitOn: function(){ 
     return [Meteor.subscribe('collection', {data:params})]; 
    }, 
    action: { 
     var myObject = Collection.findOne(); 
     this.render('myTemplate', { 
      data: function(){ 
       return myObject; 
      } 
     }); 
    } 
}; 

模板

<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 
      }); 
     }; 

    }, 
}); 

這有點不好意思,但有訣竅。

執行完路由後,getDescription幫助程序返回myObject的說明。在模糊時,我們檢查以前內容中的更改(存儲在具有焦點事件的屬性中),如果存在差異,則調用更新方法。

流星將立即通過助手返回值,但爲了避免重複的內容問題,我們在調用之前清理元素。

這是有點粗糙的元素閃爍微秒,而HTML是空的,除此之外,它的作品。

PS:使用三個括號將助手呈現爲HTML。

希望有所幫助。