2012-08-02 5 views
6

Chcę utworzyć ogólny program obsługi zdarzeń, który będę mógł ponownie użyć na elementach dom, więc nie muszę pisać płyty kotła w kółko. Myślałem, że mam to wymyślone, ale dostaję błędy.W Meteorze, w jaki sposób mogę utworzyć ogólny program obsługi zdarzeń?

Problem polega na tym, że myślę, że programy obsługi zdarzeń są powiązane w innym czasie niż potrzebuję. Może na document.ready? Gdzie myślę, że muszę dołączyć je za pomocą metody .live()? Chociaż może nie mam pojęcia o czym tu mówię.

Oto, co próbuję zrobić:

Aplikacja wielostronicowa.

Wiele kolekcji, w których należy wstawić dane.

Kod przycisku, aby wyświetlić formularz wstawiania.

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

Szablon, który pokazuje formę opartą na stronie (Controller)

{{> groups_insert}} 

Oto postać.

<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> 

Oto kod klienta służący do implementacji przycisku wyświetlającego formularz na stronie.

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

Oto moja rodzajowy obsługi zdarzeń

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; 

Błąd

Uncaught TypeError: Cannot call method 'btn_events' of undefined 

ALE, gdybym definiować procedury obsługi zdarzenia w ten sposób i nazwać w ten sposób to działa .

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

Problem nie chcę mieć do replikacji kodu całym moim miejscu w celu realizacji ładny przycisk, który można slideToggle i formę na dowolnej stronie. Gdyby udało mi się go wyodrębnić, powinienem mieć przycisk typu "Pokaż formę" na wszystkich stronach dla każdej kolekcji, którą renderuję, która pozwala na wprowadzanie danych. Co więcej, prowadzi to do możliwości utworzenia jednego formularza obsługi wszystkich formularzy, a następnie powiązania ich z kontrolerem poprzez działanie na modelu.

Wszelkie pomysły?

Odpowiedz

10

Można powiązać szablon wysokiego poziomu z elementami utworzonymi za pomocą szablonów podrzędnych. Następnie wystarczy wykonać wiązanie tylko raz. Na przykład

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

Więc jeśli kończy się tworzenie 10 różnych definicji szablonu pod ustawieniach więc jeszcze tylko do związania obsługi do jednego szablonu.

+1

Działa to świetnie. Wycofuję stary kod. Myślę, że w pewnym momencie w przeszłości nie działało to z wczesną wersją Meteora. Moje oryginalne rozwiązanie miało ponad rok. –

3

Czuję, że komplikujesz rzeczy. Dlaczego tego nie zrobić?

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

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

Ma właściwą równowagę separacji: Twój obsługi zdarzeń jest zdefiniowana raz, ale można powiedzieć, każdy szablon, który chcesz jej przyciski, aby słuchać jakiegoś zdarzenia. A jeśli to nie wystarczy, można dalej abstrakcyjne go:

Template.someTemplate.events(genericEvents); 

i być może nawet połączyć genericEvents z konkretnych wydarzeń dla tego szablonu, jeśli chciał.

1

Oto, co zrobiłem.Przykład pokazuje tylko ogólny program obsługi insertów.

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; 

Teraz tylko trzeba tworzyć szablony kierownice bez żadnego znaczącego javascript kodowanie do obsługi zdarzeń rodzajowe i drutu je w następujący sposób.

$(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()); 

Teraz nie muszę pisać żadnych szablonowych map zdarzeń do obsługi podstawowego CRUD. Mogę utworzyć dowolną liczbę szablonów kierownicy, o ile/route odpowiada nazwie kolekcji. Chociaż od czasu do czasu wykonuję pewne trudne konwersje. Zasadniczo, ogólna procedura obsługi zdarzeń koryguje zdarzenia, w oparciu o trasę aka request.controller, do kolekcji i streszcza ją poprzez wspólny model danych klient/serwer w celu sprawdzenia poprawności, a nawet kontroli dostępu, równolegle do tego, co istnieje w Meteor.

Wygląda na to, że działa dobrze i znacznie ograniczył bazę kodu. Mam tuziny kolekcji, w których nie musiałem pisać żadnych programów do obsługi map zdarzeń, ponieważ podstawowy CRUD jest obsługiwany, ale na tyle abstrakcyjny, że mogę spersonalizować sprawdzanie poprawności, bezpieczeństwo i inne sprawdzenia poprawności na modelu danych udostępnianych klient/serwer.

0

Podejście, którym podjąłem ten problem w Meteor 1.0.2, to użycie dynamicznych szablonów. Zobacz: Dan Dascalescu: canonical answer i docs.

Załóżmy, że masz zestaw ogólnych wydarzeń dołączonych do szablonu "A" i chcesz skorzystać z nich w szablonach "B", "C" i "D."

HTML:

<template name="A"> 
    {{> Template.dynamic template=myTemplate}} 
</template> 

JS:

Template.A.events({ 
    ... your event code 
}) 

zdefiniować funkcję pomocniczą dla "A", który dynamicznie który odbiera B, C lub D (...) chcesz to:

Template.A.helpers({ // dynamically insert a template 
    myTemplate: function(){ 
    if (...) return 'B'; // return a string with the name of the template to embed 
    if (...) return 'C'; 
    if (...) return 'D'; 
    } 
})  

Zdarzenia zdefiniowane w "A" będą teraz dostępne w "B", "C" i "D."

Należy zauważyć, że szablon "A" nie musi zawierać żadnego kodu HTML.

Powiązane problemy