2016-02-27 116 views
3

在過去2年多的時間裏,AngularJS工作了很多,現在開始進入MeteorJS 1.2,但有一些模板圖層對我來說很不直觀,但可能有一個簡單的解決方案。如何在本地數組更改時重新渲染流星火焰模板?

我希望有一個「創建民意調查」形式,它具有以下字段:

  • 問題,文本字段
  • 投票選項,文本字段
  • 添加選項,按鈕
  • 名單<li>基於本地options陣列的選項,中繼器
  • 列表項有一個刪除按鈕

實質上,我希望能夠填充輪詢選項字段,單擊「添加選項」並使該選項以只讀方式(純文本)在輪詢選項文本字段下方的列表重複器中呈現。

我現在的問題是,如果沒有使用ReactiveArray之類的東西,當我推送本地數組變量options中的項時,模板不會重新渲染。

這是怎麼回事?下面

代碼:

poll.create.html模板:

<template name="pollCreate"> 
    <form class="form form--create"> 
     <section class="form__section"> 
      <!-- Question Field --> 
      <input class="form__field" type="text" name="question" required> 

      <!-- Poll Options --> 
      <ul class="form__list"> 

       <!-- Poll option form field --> 
       <li class="form__list-item form__list-item--creator"> 
        <input class="form__field" type="text" name="pollOption"> 
        <button class="form__button--add" type="button">&plus;</button> 
       </li> 

       <!-- Render the options added above --> 
       {{#each option in optionList}} 
       <li class="form__list-item--option" data-index="{{option.index}}"> 
        <span class="form__list-item-value">{{option.label}}</span> 
        <button type="button" class="form__button--delete">&times;</button> 
       </li> 
       {{/each}} 
      </ul> 
     </section> 

     <button class="form__button--submit" type="submit">Create Poll</button> 
     <button class="form__button--reset" type="reset">Clear Fields</button> 
    </form> 
</template> 

poll.create.client.jsPolls = new Mongo.Collection("polls")是在服務器文件)

// Setup 
Template.pollCreate.onCreated(function() { 

    // Local poll variable to capture the options in. 
    this.options = [ 
     { index: 0, label: 'BurgerBurger' }, 
     { index: 1, label: 'BetterBurger' } 
    ]; 

}); 

// Events 
Template.pollCreate.events({ 
    /** 
    * Adds an option to the local array for saving as part of the submit in the Posts.insert call. 
    * @param event 
    * @param instance 
    */ 
    'click .form__button--add': function (event, instance) { 
     event.preventDefault(); 

     // Get current option element 
     var option = instance.find('[name="pollOption"]'); 

     // Store in a local array 
     instance.options.push({ 
      index: instance.options.length, 
      label: option.value 
     }); 

     // Clear field so it's ready for another option 
     option.value = ''; 
    }, 
    /** 
    * Delete an existing option. 
    * @param event 
    * @param instance Template.instance 
    */ 
    'click .form__button--delete': function (event, instance) { 
     event.preventDefault(); 

     var listItemElement = event.target.parentNode; 
     var itemIndex = instance.$(listItemElement).data('index'); 

     // Delete option from reactive source array 
     instance.options.splice(itemIndex, 1); 
    }, 
    /** 
    * Submit the Poll Create form which will run Polls.insert with the question and options 
    * @param event 
    * @param instance 
    */ 
    'submit .form--create': function (event, instance) { 
     event.preventDefault(); 

     var question = instance.find('[name="question"]'); 
     var options = instance.options; 

     var poll = { 
      question: question.value, 
      options: options 
     }; 

     Polls.insert(poll); 
    } 
}); 

// Helpers 
Template.pollCreate.helpers({ 
    optionList: function() { 
     const instance = Template.instance(); 
     return instance.options; 
    } 
}); 

我可以看到instance.options數組值改變,因爲我推或拼接選項,但它似乎並不重要 - 提供模板,選項列表不會改變。

我在這裏做錯了什麼?

回答

1

無論何時您希望ui進行被動更新,您都需要有兩件事:(1)反應性數據源和(2)反應性上下文。

現在你已經得到了被動的上下文 - 這就是模板助手optionList,當它引用的被動數據源發生變化時,它將重新呈現它。問題是選項列表不是一個被動數據源,它只是一個香草數組。所以當Templace.instance().options數組發生變化時,助手不知道要重新渲染它。

修復的方法是非常簡單 - 只是讓Template.instance.options反應數據源,通過使用流星內置的活性結構ReactiveVarReactiveDict或使用MiniMongo之一。你提到的ReactiveArray也會起作用 - 我相信這是社區維護的,而不是核心軟件包,但它是一樣的想法。

這裏的最快,最簡單的解決方案是將整個數組保存到一個ReactiveVar

Template.pollCreate.onCreated(function(){ 
    this.options = new ReactiveVar([ 
    { index: 0, label: 'BurgerBurger' }, 
    { index: 1, label: 'BetterBurger' } 
    ]); 
}); 

Template.pollCreate.helpers({ 
    optionList({ 
    return Template.instance().options.get(); 
    }) 
}); 

這應該做到這一點。

+0

嘿,謝謝你。只是試了一下,很好地工作。現在唯一的問題是(我可能會錯過某些東西),但我不能像'本地數組'那樣與'ReactiveVar'交互?即直接調用'array.push'和'array.splice'。因此,通過首先調用ReactiveVar.get()方法,然後修改結果然後通過ReactiveVar.set(new)重新設置ReactiveVar來更改內容的唯一方法是? – Jannis

+0

那就對了。可能爲什麼包創建者構建ReactiveArray –

+0

再次感謝,我剛剛玩過這個場景,但是使用MiniMongo創建一個本地'Options'集合,然後使用'insert','remove'並最終使用'.find()。 fetch()'將選項保存爲輪詢的一部分,從代碼模式的角度來看,我感覺更好。在這個用例中使用這些客戶端只有mongo集合有什麼缺點嗎? – Jannis