2017-04-02 113 views
0

使用流星模板和流路由器,我發現如果我創建一個新元素,那麼頁面不會更新以顯示它,但如果我刪除相同的元素,它會立即消失。這裏是模板代碼:流星模板更新不一致

<template name="EditProject"> 
    ... 
    {{#each currentCounts }} 
     <div class="count-box">{{> CountDelete }}</div> 
    {{/each}} 
    ... 
    <btn class="btn waves-effect waves-light h-button" id="add-count">Add Count</btn> 
    ... 
</template> 

<template name="CountDelete"> 
    <div class="card blue-grey lighten-2 count-box"> 
     <div class="card-content white-text"> 
      <span class="card-title"> 
       {{ name }} 
      </span> 
      {{ notes }} 
     </div> 
     <div class="card-action"> 
      <btn class="btn waves-effect waves-light delete-count"> 
       <i class="mdi mdi-delete"></i> 
      </btn> 
      <a class="btn waves-effect waves-light" href="/edit_count/{{ _id }}"> 
       <i class="mdi mdi-pencil"></i> 
      </a> 
     </div> 
    </div> 
</template> 

currentCounts來源是這樣的:

Template.EditProject.helpers({ 
    currentCounts: function() { 
     var projectId = FlowRouter.getParam('projectId'); 
     const project = Projects.findOne(projectId); 
     var counts = Counts.find({ 
      _id: { $in: project.counts } 
      }, 
      { 
       sort: { sort_order: -1 } 
      } 
     ); 
     return counts; 
    } 
}) 

如前所述,點擊一個.delete-count按鈕刪除相關的計數,也使得UI更新,以表明它具有不見了。添加一個計數(點擊#add-count)會正確創建計數,但頁面不會更新。有一個簡短的閃爍,但僅此而已,並刷新頁面導致新的計數顯示。任何人都可以提出發生了什麼事?

編輯:這裏的認購,如在評論要求:

Template.EditProject.onCreated(function() { 
    var self = this; 
    self.autorun(function() { 
     var projectId = FlowRouter.getParam('projectId'); 
     self.subscribe('single-project',projectId); 
     self.subscribe('project-counts',projectId); 
    }) 
}) 

進一步編輯:

當第一次訪問該路由的頁面呈現,因爲它應該,表示用幾大罪狀清單{{#each currentCounts}}。如果我刪除其中一個計數,它會立即從屏幕上消失,但如果我添加一個新的計數器,它將不會顯示,直到我刷新頁面。

另一個編輯:

監聽器和服務器出版物代碼(在服務器/ main.js)加入請求。奇怪的是,當再次啓動應用程序時,一切都開始按照它應該的方式運行,但在幾分鐘內,我已經描述了同樣的行爲,重新進行自我評估。

Meteor.publish('project-counts', function projectPublication(projectId) { 
    let project = Projects.findOne({_id: projectId, knitter: this.userId}); 
    return Counts.find({_id: { $in: project.counts }}); 
}); 
Meteor.publish('single-project', function projectPublication(projectId) { 
    return Projects.find({_id: projectId, knitter: this.userId}); 
}); 

'click #add-count'(event) { 
    //TODO: Check for duplicate count name 
    var projectId = FlowRouter.getParam('projectId'); 
    var countName = $('#new-count').val(); 
    var countNotes = $('#new-count-notes').val(); 

    if (!countName) { 
     $("#errors-go-here").empty(); 
     Blaze.renderWithData(Template.EditProjectErrors, { 
      errors: ['You must supply a name for the new count.'] 
     }, $("#errors-go-here")[0]) 
     $('.modal').modal(); 
     $('#validation-errors').modal('open'); 
     return; 
    } 

Template.EditProject.events({ 
    ... 
    Meteor.call('projects.add-count',projectId,countName,countNotes, function(error) { 
      if (error) { 
       console.log("Count add error: " + error); 
       Materialize.toast('Failed to add count \'' + countName + '\'!', 3000, 'orange darken-4'); 
       return false; 
      } else { 
       Materialize.toast('Count \'' + countName + '\' added!', 3000, 'blue-grey'); 
       $('#new-count').val(null); 
       $('#new-count-notes').val(null); 
       // Running this makes the missing count show up, but this is clearly not the right way to do it... 
       //location.reload(); 
      } 
     }); 
    }, 
    ... 
)} 



Template.CountDelete.events({ 
    'click .delete-count'(event) { 
     var self = this; 
     var projectId = FlowRouter.getParam('projectId'); 
     var countId = self._id; 
     const count = Counts.findOne(countId); 
     const name = count.name; 

     Meteor.call('projects.delete-count',projectId,countId, function(error) { 
      if (error) { 
       console.log("Count add error: " + error); 
       Materialize.toast('Failed to delete count \'' + name + '\'!', 3000, 'orange darken-4'); 
       return false; 
      } else { 
       Materialize.toast('Count \'' + count.name + '\' deleted!', 3000, 'blue-grey'); 
      } 
     }); 

    }, 

}) 

更多信息:我發現一旦頁面被加載,它的行爲就像它應該那樣。但是,如果它被重新加載,那麼它開始行爲不端。所以,我最初並沒有注意到由於代碼更改導致頁面被Meteor刷新的正確行爲。

+0

您訂閱計數集合的位置是否位於editproject模板的路徑的onWait函數或模板的onCreated? –

+0

我已更新帖子以顯示計數(和項目)的訂閱位置。 – knirirr

+0

從我所瞭解的情況來看,您從項目集合中獲得一條記錄,然後您正在使用該項目ID搜索Counts集合,並且希望計數集合與您訂閱的項目計數相同。在Counts集合中,您是否發現返回所有包含_id = project.id的行 –

回答

1

要完整,您應該也可以共享方法代碼(即'projects.add-count''projects.delete-count')。

這就是說,我懷疑他們更新_id的文檔的counts數組字段等於projectIdProjects集合。

在這種情況下,查看您的'project-counts'發佈,我們發現它取決於Projects.findOne查詢,該查詢在服務器端與標準Meteor無關。

因此什麼,當你添加一個「計數」的情況是,一個新的文檔添加到Counts集合,其_id很可能正確地記錄在該項目的counts場,但是這並不能重新執行您的出版物的代碼。因此,遊標選擇器查詢未更改,並且您的客戶端在其集合Counts中未收到任何修改。

假設客戶端和服務器都加載了方法代碼,客戶端會執行一個存根/模擬來插入這個新文檔,並在本地更新項目的counts,從而觸發UI更新。

但是,然後您的服務器也執行該方法,這會導致發佈沒有變化,因此Counts中的新文檔不會發送到客戶端,從而將其隱藏起來。這會產生您觀察到的閃爍。現在

當你Counts刪除文件,我們可以假設,特別是從Counts集合,然後更新出版物光標刪除它,這就是爲什麼你的UI正確反映刪除,即使發佈查詢選擇器沒有改變。

最後,當你刷新頁面,您的出版物代碼是完全重新評估,在Projects集合,它導致了正確的查詢選擇,因此你的新的光標現在包括新採用了最新版本的文件在Counts中添加文檔。

然後要解決您的問題,您應該嘗試使用被動連接或發佈組合軟件包。

E.g.請參閱https://stackoverflow.com/a/32920733/5108796Meteor.publish: publish collection which depends on other collection

+0

感謝您提供非常有用的解釋。你確實對'add-count'和'delete-count'方法的正確性,我發現通過添加鏈接和更新相關訂閱的軟件包可以解決問題。 – knirirr