16

同じページの複数の(任意の数の)場所に同じハンドルバーテンプレートをレンダリングしています。各テンプレート内で、divの表示を切り替えるボタンが必要です。この状態をで保存するとSession.set、1つのボタンをクリックすると、すべてのテンプレートインスタンス化のすべてのdivが明らかに切り替わりますが、これは望ましくありません。

テンプレートインスタンスのデータコンテキスト(およびコールバックにバインドさthis.dataれている)に状態を保存できますが、これには2つの問題があります。Template.myTemplate.renderedTemplate.myTemplate.created

  1. this.dataはリアクティブなデータソースではないため、divに伝播されません
  2. ( meteor-coreTemplate.myTemplate.eventsで説明されているように)のテンプレートインスタンスにアクセスできません

最後に、どういうわけかそれをコレクションに保存することができました。しかし、レンダリングされた各テンプレートの状態を一意に識別するにはどうすればよいでしょうか。jQueryにはハッキーな方法もあるかもしれませんが、それはリアクティブテンプレートで動作するはずのMeteorアプリを開発したい方法ではありません。特に、そのテンプレートがより複雑になると。

何かが足りないのでしょうか、$scopeそれともテンプレートのインスタンス化ごとに渡されるAngularJSのコントローラーに相当するものが本当にないのでしょうか?

更新:私はこのようなことを考えていました。

template.html:

<template name="jsonObject">
    <input type="button" />
    <div class="{{hidden}}">content</div>
</template>

client.js:

Template.jsonObject.hidden = function(){
    var ret = "";
    if (this._hidden) {
        ret = "hidden";
    }
    return ret;
};

Template.jsonObject.events({
    'click input' : function(event, template){
        template.data._hidden = true;
    }
});
4

4 に答える 4

2

これが、テンプレートごとのインスタンスのリアクティブ ソースを実現した方法です

絶滅ステータスが絶滅に設定されているときに、恐竜の絶滅の理由をユーザーに尋ねたいだけです。

<template name="dinosaur">
   <label for="extinction-status">Extinction status</label>
   <select name="extinction-status">
     <option value="not-extinct">Not extinct</option>
     <option value="extinct">Extinct</option>
   </select>
   {{#if isExtinct extinctStatus newExtinctStatus extinctStatusDep}}
   <label for="extinction-reason">Reason for extinction</label>
   <input name="extinction-reason" type="text" placeholder="Why is it extinct?"/>
   {{/if}}
</template>

reason フィールドをリアクティブに表示するには、テンプレート関数Deps.Dependencyに toを追加します。this.datacreated

Template.dinosaur.created = function() {
  this.data.newExtinctStatus = null;
  this.data.extinctStatusDep = new Deps.Dependency;
};

ユーザーが消去ステータスの選択を変更したときをリッスンし、 を更新してnewExtinctStatusを呼び出しchangedましたextinctStatusDep

Template.dinosaur.events({
  'change [name="extinction-status"]': function(event, template) {
    var extinctStatus = $(event.target).val();
    template.data.newExtinctStatus = extinctStatus;
    template.data.extinctStatusDep.changed();
  }
});

Deps.Dependencyヘルパーでは、渡されたものに依存していると言います

Template.dinosaur.helpers({
  isExtinct: function(status, newStatus, statusDep) {
    if (statusDep) {
      statusDep.depend();
    }
    if (newStatus) {
      if (newStatus == 'extinct') {
        return true;
      }
    else if (status == 'extinct') {
        // No new status is set, so use the original.
        return true;
    }
  }
});

への追加を伴うちょっとしたハックですが、this.dataテンプレートごとの反応性が可能になり、Collectionまだ何かに保存されていないデータに依存する場合に役立ちます。

于 2013-08-26T12:52:03.123 に答える
1

更新された回答 - METEOR 0.8.3

Meteor はUI._templateInstance()、テンプレート ヘルパーのテンプレート インスタンスへのアクセスを提供する関数を提供するようになりました。これにより、よりクリーンな実装が可能になります。

1. 以下の HTML コードで、{{#with templateInstanceId=getTemplateInstanceId}}

2. JS コードを次のコードに置き換えます。

var templateInstanceId = 0;

Template.divWithToggleButton.created= function() 
    { 
    this.templateInstanceId = ++templateInstanceId;
    };

Template.divWithToggleButton.events(
    {
    'click button': function(event, template) 
        {
        Session.set("visible", template.templateInstanceId);
        },
    });

Template.divWithToggleButton.visible= function() 
    { 
    return Session.equals("visible", UI._templateInstance().templateInstanceId);
    };

以前の回答 私のプロジェクトでも同じ要件がありましたSession.set

これは、コンテキストの置換と「スライドする」一意のインスタンス ID を使用した私の単純なハックです (これについては後で詳しく説明します)。

クライアント コードの任意の場所に、次のように入力します。

var templateInstanceId = 0;

UI.registerHelper('getTemplateInstanceId', function()
{
    return templateInstanceId++;
});

次に{{#with templateInstanceId=getTemplateInstanceId }}、インスタンスを一意に識別したいテンプレートで使用します。あなたの例では、次のようになります(テストされていません):

HTML:

<!-- Div with a toggle visibility button. Use as a Block Helpers (with # instead of >) -->
<template name="divWithToggleButton">
    {{#with templateInstanceId=getTemplateInstanceId }}
    <div>
        <!-- The 'toggle visibility' button -->
        <button type="button">Toggle Visibility</button>

        <!-- The div content -->
        {{#if visible}}
            {{> UI.contentBlock}}
        {{/if}}
    </div>
    {{/with}}
</template>

JS (クライアント コード):

Template.divWithToggleButton.events(
{
    'click button': function(event, template) 
    {
        Session.set("visible", this.templateInstanceId);
    },
});

Template.divWithToggleButton.visible= function() 
{ 
    return Session.equals("visible", this.templateInstanceId);
};

この奇妙な「スライドする」一意のインスタンス ID について:

この ID はテンプレートのレンダリングごとに更新されますが、他の方法は見つかりませんでした。これは、新しいレンダリングが Session に格納されている一意の ID を無効にすることを意味します。div にリアクティブ データ ソースが含まれている場合、新しいレンダリングが発生します。ケースによっては、これが問題になる場合とそうでない場合があります。

于 2014-04-26T10:18:22.057 に答える
0

流星核に関する議論は時代遅れだと思います (最近のことですが)。ドキュメント(以下に引用)によると、これは可能であるはずです:

Template.myTemplate.events({
   foo: function(event, template) {
      var _div = template.find('...');
   }
});

ハンドラー関数は 2 つの引数を受け取ります。イベントに関する情報を含むオブジェクトである event と、ハンドラーが定義されているテンプレートのテンプレート インスタンスである template です。ハンドラーは、イベントを処理している現在の要素のコンテキストに応じて、これでいくつかの追加のコンテキスト データも受け取ります。Handlebars テンプレートでは、要素のコンテキストは、その要素が発生する Handlebars データ コンテキストであり、#with や #each などのブロック ヘルパーによって設定されます。

アップデート

非表示にできる各 div に一意の ID があると仮定すると、次のようなことを試してみたらどうでしょうか? 私はそれをテストしていません。

Template.jsonObject.hidden = function(){
    var _id = $(".classOfPossibleHiddenDiv").prop("id");
    return Session.get(_id) || false;
};

Template.jsonObject.events({
    'click input' : function(event, template){
        Session.set($(template.find(".classOfPossibleHiddenDiv")).prop("id"), true);
    }
});
于 2013-02-07T14:56:26.230 に答える