6

ボイラー プレートを何度も記述する必要がないように、dom 要素で再利用できる汎用イベント ハンドラーを作成したいと考えています。私はそれを理解したと思っていましたが、エラーが発生しています。

私が抱えている問題は、イベント ハンドラーが必要とは異なる時間にバインドされていると思うことです。多分でdocument.ready.live()メソッドでそれらを添付する必要があると思う場所はどこですか? 私はここで何について話しているのか分からないかもしれませんが。

これが私がやろうとしていることです:

マルチページアプリケーション。

データを挿入する必要がある複数のコレクション。

挿入フォームを表示するためのボタン コード。

<button id="btnShowInsert" class="btn btn-success" rel="tooltip" title="add group">
    <i id="btnIcon" class="icon-plus-sign icon-white"></i>
</button>

ページに基づいてフォームを表示するテンプレート (コントローラー)

{{> groups_insert}}

これがフォームです。

<template name="groups_insert">
    {{#if acl_check}}
    {{> alert}}
    < p>
      < form class="form-horizontal well hide" id="insert">
        <fieldset>
          < div class="control-group">
            < label class="control-label" for="name">Name</label>
            < div class="controls">
              < input type="text" class="input-xlarge" id="name" name="name">
            < /div>
          < /div>
          < div class="form-actions well">
            < button id="btnReset" type="reset" class="btn btn-large">Reset</button>
            < button id="btnSubmit" type="button" class="btn btn-primary btn-large">Submit</button>
          < /div>
        < /fieldset>
      < /form>
    < /p>
  {{/if}}
< /template>

ページにフォームを表示するボタンを実装するクライアント コードを次に示します。

Template.groups.events[ Meteor.eventhandler.btn_events('#btnShowInsert') ] =  Meteor.eventhandler.make_btn_show_insert_form_click_handler();

これが私の一般的なイベントハンドラーです:

var EventHandler = Base.extend({
  btn_events: function(selector) {
    return 'click ' + selector; //, keydown '+selector+', focusout '+selector;
  },

  make_btn_show_insert_form_click_handler: function(){
    //var click = options.click || function () {};
    return function (event) {
      if (event.type === "click") {
        event.stopPropagation();
        event.preventDefault;
        try{
          if ($('#btnIcon').hasClass('icon-plus-sign') ) {
            $('#btnIcon').removeClass('icon-plus-sign');
            $('#btnIcon').addClass('icon-minus-sign');
          } else {
            $('#btnIcon').removeClass('icon-minus-sign');
            $('#btnIcon').addClass('icon-plus-sign');
          }

          $('#insert').slideToggle('slow', 'swing');

        } catch(error) {
          Alert.setAlert('Error', 'Critical Error: ' + error, 'alert-error');
        }
      }
    }
  },

});

Meteor.eventhandler = new EventHandler;

エラー

キャッチされていない TypeError: 未定義のメソッド 'btn_events' を呼び出せません

しかし、この方法でイベント ハンドラーを定義し、この方法で呼び出すと、機能します。

Template.groups.events[ btn_events('#btnShowInsert') ] =  make_btn_show_insert_form_click_handler();

var btn_events = function (selector) {
  return 'click ' + selector; //, keydown '+selector+', focusout '+selector;
};


var make_btn_show_insert_form_click_handler = 
function () {
  //var click = options.click || function () {};
  console.log( Meteor.request.controller );

  return function (event) {
    if (event.type === "click") {
      event.stopPropagation();
      event.preventDefault;
      try{
        if ($('#btnIcon').hasClass('icon-plus-sign') ) {
          $('#btnIcon').removeClass('icon-plus-sign');
          $('#btnIcon').addClass('icon-minus-sign');
        } else {
          $('#btnIcon').removeClass('icon-minus-sign');
          $('#btnIcon').addClass('icon-plus-sign');
        }

        $('#insert').slideToggle('slow', 'swing');

      } catch(error) {
        Alert.setAlert('Error', 'Critical Error: ' + error, 'alert-error');
      }
    }
  }
};

問題任意のページにフォームを作成
できる便利なボタンを実装するために、サイト全体にコードを複製する必要はありません。slideToggle抽象化できれば、データ入力を許可するレンダリング中のコレクションのすべてのページにフォームの表示タイプのボタンを配置できるはずです。同様に、これにより、すべてのフォームに対して 1 つのフォーム ハンドラーを作成し、モデルへのアクションを介してそれらをコントローラーに結び付けることができます。

何か案は?

4

4 に答える 4

10

子テンプレートで作成された要素に高レベルのテンプレートをバインドできます。その後、バインディングを 1 回だけ行う必要があります。例えば

HTML:

<template name="settings">
    {{> login_settings }}
    {{> account_settings }}
    {{> data_settings }}
</template>

<template name="login_settings">
  <btn class="slideToggle">Slide me for login!</btn>
</template>

<template name="account_settings">
  <btn class="slideToggle">Slide me for account!</btn>
</template>

<template name="data_settings">
  <btn class="slideToggle">Slide me for data!</btn>
</template>

JavaScript:

Template.settings.events {
  'click .slideToggle': function() {
    var clickedElement = event.target;
    // add/remove CSS classes to clicked element
  }
};

したがって、設定で 10 個の異なるテンプレート定義を作成することになった場合でも、ハンドラーを 1 つのテンプレートにバインドするだけで済みます。

于 2013-12-08T03:14:29.593 に答える
3

物事を複雑にしすぎているように感じます。なぜこれをしないのですか?

Template.someTemplate.events({
  'click .button': buttonClicked
});

function buttonClicked(evt) {
  // DRY code to handle a button being clicked
}

これは適切な分離のバランスをとっています。イベント ハンドラーは 1 回定義されますが、ボタンで何らかのイベントをリッスンするように各テンプレートに指示できます。それが十分でない場合は、さらに抽象化できます。

Template.someTemplate.events(genericEvents);

また、必要に応じて、genericEvents をそのテンプレートの特定のイベントとマージすることもできます。

于 2012-12-22T13:55:52.163 に答える
1

これが私がやったことです。この例では、一般的な挿入ハンドラーのみを示しています。

var EventHandler = Base.extend({

btnClickHandler: function(){
    return function (event) {
      event.preventDefault();
      Meteor.eventhandler[event.currentTarget.id](event);
    }
  },
insert: function(event){
    event.preventDefault();
    var params =  $('#insert-form').toJSON(); 
    try{
      window[Meteor.request.controller.capitalise()]['validateParams'](params);
      var ts = new Date();
      params.client_updated = ts;
      var has_popup = params.has_popup;
      delete params.has_popup;
      window[Meteor.request.controller.capitalise()]['insert'](params, function(error, _id){
        if(error){
          Alert.setAlert('Error', error, 'alert-error', true, has_popup);
        } else {
          Alert.setAlert('Success', 'Record successfully created.', 'alert-success', true, has_popup);
          $("#insert-form").reset();
          Meteor.flush();
        }
      });
    } catch(error) {
      Alert.setAlert('Error', error, 'alert-error', true, params.has_popup);
    }
  }
 });

 Meteor.eventhandler = new EventHandler;

さて、一般的なイベントを処理するための重要な JavaScript コーディングを行わずにハンドルバー テンプレートを作成し、次のように接続するだけです。

$(document).on("click", '#print', Meteor.eventhandler.btnClickHandler());
$(document).on("click", '#insert', Meteor.eventhandler.btnClickHandler());
$(document).on("click", '#remove', Meteor.eventhandler.btnClickHandler());
$(document).on("click", '#removeSubField', Meteor.eventhandler.btnClickHandler());
$(document).on("click", '#insertSubField', Meteor.eventhandler.btnClickHandler())
$(document).on("click", '#update', Meteor.eventhandler.btnClickHandler());
$(document).on("click", '#updateSubField', Meteor.eventhandler.btnClickHandler());
$(document).on("click", "#toggleActive", Meteor.eventhandler.btnClickHandler());
$(document).on("click", "#toggleChild", Meteor.eventhandler.btnClickHandler());

これで、基本的な CRUD を処理するためにテンプレート イベント マップを作成する必要がなくなりました。/route がコレクション名に対応する限り、任意の数のハンドルバー テンプレートを作成できます。私は時々トリッキーな変換を行いますが。基本的に、ジェネリック イベント ハンドラーは、request.controller とも呼ばれるルートに基づいてイベントをコレクションに接続し、クライアント/サーバー共有データ モデルを介してそれを抽象化し、検証や、Meteor に存在するものと一緒にアクセス制御を行います。

うまく機能しているようで、コード ベースが大幅に削減されました。基本的な CRUD は処理されますが、クライアント/サーバー共有データ モデルの検証、セキュリティ、その他の健全性チェックをカスタマイズできるほど十分に抽象化されているため、イベント マップ ハンドラーを記述する必要のないコレクションが多数あります。

于 2012-12-23T15:35:49.047 に答える