Совместное использование шаблонов в 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: { ... },
});