Метеор: сохранение флагов ClassName
У меня проблемы с использованием метода сохранения в метеоре. Кажется, он не делает то, что я хочу.
По сути, у меня есть три вложенных шаблона, которые при рендеринге выглядят примерно так в закрытом состоянии:
<div class="Dropdown"><!--From Template1-->
<div class="Group"><!--From Template2-->
<div class="SubGroup"><!--From Template3-->
I'm the subgroup's content!
</div>
</div>
</div>
Для просмотра содержимого в узле.SubGroup все упаковщики шаблонов должны иметь имя класса.Open. Это делается на событии клика. Вот как это выглядит в открытом состоянии:
<div class="Dropdown Open"><!--From Template1-->
<div class="Group Open"><!--From Template2-->
<div class="SubGroup Open"><!--From Template3-->
I'm the subgroup's content!
</div>
</div>
</div>
Проблема заключается в том, что когда события запускаются и изменяют базу данных из содержимого.SubGroup, создается впечатление, что Template2 и Template3 повторно визуализируются и теряют свой программно примененный класс.Open.
Я пытался использовать Template.Template2.preserve(['.Group']);
Я думаю, что на каждом шаблоне может присутствовать почти каждый селектор. Я также пробовал {{#constant}} и {{#isolated}} помощников, но пока не получил ожидаемых результатов с ними.
Как правильно помешать Метеору уничтожить имена моих классов?
1 ответ
Вы должны использовать переменные Session в сочетании с помощниками Handlebars.
<template name="dropdown">
opened helper resolves to current dropdown state
<div class="dropdown {{opened}}">
iterate over each group using a cursor
{{#each groups}}
call subtemplate fed with current group document
fetched from the cursor
{{> group}}
{{/each}}
</div>
</template>
<template name="group">
assign a unique id to the group div, using the document._id
<div id="group-{{_id}}" class="group {{opened}}">
... and so on
</div>
</template>
Template.dropdown.helpers({
opened:function(){
// Session variable will be undefined on first page view (closed state)
// then it will have the value set in the click handler
return Session.get("dropdown-opened")?"open":"";
},
groups:function(){
return Groups.find();
}
});
Template.dropdown.events({
"click .dropdown":function(){
var opened=Session.get("dropdown-opened");
// toggle open state
Session.set("dropdown-opened",!opened);
}
});
// executed once on each template instance creation
Template.group.created=function(){
// this.data._id is the fetched document._id
// comment this line if you don't want your stuff to be collapsed
// when the template is re-created (ie when you change page)
Session.set("group-"+this.data._id+"-opened",false);
};
Template.group.helpers({
opened:function(){
// this._id is the fetched document._id
return Session.get("group-"+this._id+"-opened")?"open":"";
},
subGroups:function(){...}
});
Template.group.events({
"click .group":function(event,template){
// once again, template.data._id corresponds to the id of the
// document used to feed the group template
var sessionKey="group-"+template.data._id+"-opened";
var opened=Session.get(sessionKey);
Session.set(sessionKey,!opened);
}
});
Это непроверенный код, но я делаю аналогичные вещи в своем приложении, и это работает как шарм. Я думаю, что это способ Meteor (Session+ помощники) для достижения такого рода вещей (в отличие от использования jQuery для манипулирования именами DOM и классов). К сожалению, этот тип шаблона довольно многословен и может быть немного неясным для разработчиков, начинающих разработку классического интерфейсного веб-приложения JS без Meteor, но я уверен, что это будет улучшено.