Метеор: сохранение флагов 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, но я уверен, что это будет улучшено.

Другие вопросы по тегам