Совместное использование шаблонов в Meteor

Что делать, если у меня есть два шаблона руля, которые хотят проверить возвращаемое значение одной и той же функции? Есть ли правильный способ сделать это? Очевидно, я мог бы это сделать:

var say_foo = function() {
  alert('foo');
};

Template.foo.say_foo = say_foo;
Template.bar.say_foo = say_foo;

Но есть ли способ сделать это прямо через объект Template? Поскольку это JavaScript, я могу назначить функцию любому свойству любого объекта, но я попытался сделать:

Template.say_foo = function() { alert('foo'); };

и, конечно, шаблоны не найдут эту функцию.

Просто любопытно о лучших методах и т.п. Спасибо!

Ответы

Ответ 1

Согласно документации Meteor, правильным способом было бы использовать пространство имен UI, которое будет привязываться к любому используемому движку шаблона, вместо прямого использования Handlebars или космосборников. Вот ссылка в документации. http://docs.meteor.com/#ui_registerhelper

Итак, для универсальной функции, доступной из любого используемого шаблона в client.js:

UI.registerHelper('stub', function() {
     // code
});

Забастовкa >

Обновление:

По-видимому, документы вернулись к использованию:

Template.registerHelper('stub', function() {
     // code
});

Затем в файле html используйте {{stub}} для доступа к переменной.

Ответ 2

Я думаю, что лучшая версия будет (если вы используете Handlebars, которая по умолчанию):

Template.registerHelper('my_helper', function() {
     // code
});

Вы можете вызвать это из любого шаблона, используя {{my_helper}}!

Надеюсь, это поможет:)

Ответ 3

Вот что я придумал, чтобы решить проблему. Это делается с использованием CoffeeScript. Если вы не используете CoffeeScript, вы можете преобразовать его в JavaScript здесь.

Сначала определите функцию extendTemplate:

extendTemplate = (template, mixin) ->
  helpers = ({name, method} for name, method of mixin when name isnt "events")
  template[obj.name] = obj.method for obj in helpers

  if mixin.events?
    template.events?.call(template, mixin.events)

  template

Затем объявите объект с помощью помощников и событий (мой называется loginMixin), который вы хотите разделить на несколько шаблонов:

loginMixin =
  merge_with_email: ->
    return Session.get 'account_merge__merge_with_email'

  events:
    'click button#merge_login': (event, template) ->

      email = $(template.find('#email')).val()
      password = $(template.find('#password')).val()

      Meteor.loginWithPassword email, password, (error)->
        if error
          console.error "Failed to login."

      return false

Затем, после объявления ваших шаблонов, вы можете расширить их с помощью вышеуказанного mixin. Со следующим кодом я расширяю шаблоны register и login:

extendTemplate Template.register, loginMixin
extendTemplate Template.login, loginMixin

Наконец, вот как выглядит мой login.html:

<template name="login">
    <div class="alert">
        <a class="close" data-dismiss="alert" href="#">×</a>
        <h4 class="alert-heading">Merge accounts</h4>
        <form id="register_form" class="form-inline" action="#">
            <p class="help-block">Please login with {{merge_with_email}}.</p>
            <label for="email">Email:</label>
            <input id="email" type="text" class="input-medium" />
            <label for="password">Password:</label>
            <input id="password" type="password" class="input-medium" />
            <button class="btn" id="merge_login">Login</button>
        </form>
    </div>
</template>

Так как я также расширил свой шаблон register, register.html также может использовать {{merge_with_email}} и также иметь событие click кнопки merge_login.

Ответ 4

С Meteor 1.0 здесь, похоже, это изменилось. После некоторого копания я обнаружил, что теперь вы можете использовать следующее для повторного использования кода между помощниками:

https://docs.meteor.com/#/full/template_registerhelper

Template.registerHelper("checkedIf",function(value){
  return (value)? "checked":"";
});

Это делает его доступным для всех помощников!

Ответ 5

Не уверен, что я понимаю, что вы просите, но я не вижу ничего плохого в том, что вы делаете, - вы назначили функцию переменной, чтобы повторно использовать ее несколько раз.

Если вам нужно набрать меньше или иметь, скажем, 20 разных шаблонов, повторно использовать его, а не 2, вы можете сделать что-то вроде этого:

var templates = ['foo', 'bar', 'baz', 'barz', 'bliz', blaz'];
for (var i=0; i < templates.length; i++) { 
    Template[templates[i]].say_foo = say_foo;
}

Но ИМО это менее читаемо, и нет никакой реальной необходимости это делать.

EDIT - лучшее решение

Просто понял, почему вы можете это сделать - чтобы каждый шаблон имел атрибут say_foo, поэтому вам нужно беспокоиться о его добавлении вручную каждый раз, когда вы создаете новый шаблон, вы можете сделать это:

for (var t in Template)
    Template[t].say_foo = say_foo;

Ответ 6

Ваш текущий подход должен работать. Несколько более короткая версия:

Template.foo.say_foo = 
Template.bar.say_foo = function() { alert('foo'); };

Ответ 7

После беспорядка с превосходным ответом Gezim, который я понял в Meteor 1.3+, вы можете просто запустить:

Template.register.helpers(MyMixin.helpers);
Template.register.events(MyMixin.helpers);

Но если вы хотите функцию extendTemplate:

// Note: above code is probably simpler.

function extendTemplate(template, mixin) {
  if (mixin.helpers && template.helpers) {
    template.helpers(mixin.helpers);
  }
  if (mixin.events && template.events) {
    template.events(mixin.events);
  }
  return template;
};

extendTemplate(Template.register, {
  events: { ... },
  helpers: { ... },
});