Метеор: принудительная визуализация элемента

1

У меня есть общий шаблон, используемый несколько раз в моем приложении:

<template name="genericCollapse">
  {{data-1}}
  <a href=# class='collapsed' data-toggle='collapse'
     data-target='#uniqueId'>Show/hide data-2</a>
  <div class='collapse' id='uniqueId'>
    {{data-2}}
  </div>
</template>

Нажимая в другом месте приложения, данные-1 и данные-2 изменяются одновременно (используя сеансовые Vars). Однако, если шаблон уже находится на экране, изменяются только данные-1 и данные-2, но статус развала div остается (очевидно) неизменным. Если он был открыт раньше, он остается открытым.

Я хочу добиться, чтобы всякий раз, когда данные 1/данные-2 меняются, div, а также a вынуждены быть в состоянии снова свернуты. Я попытался добавить

<a href=# class='{{collapsed}}'

Template.genericCollapse.helpers({
  collapsed () {return "collapsed " + Random.Id()},
})

что не только довольно уродливо, но и не помогает, потому что класс div по-прежнему остается "крах шоу" и даже со вторым помощником для div, я не могу избавиться от "шоу".

Повторное рендеринг всего шаблона также будет приемлемым, но мне сложно определить parentNode для вызова Blaze.render() - он никогда не бывает прежним - и я также не уверен, где правильно разместить такой вызов.

Как это делается?

Теги:
meteor
meteor-blaze

4 ответа

1
Лучший ответ

Похоже, вы боретесь с бутстрапом. Класс show добавляется бутстрапом, когда вы нажимаете на ссылку, правильно? Поскольку этот класс не задан вашей разметкой html, вам необходимо удалить ее самостоятельно, когда ваши базовые данные будут изменены. Вы можете сделать это, наблюдая изменения в своих данных, а затем напрямую изменяя DOM.

Вот базовый пример:

Template.myTemplate.onCreated(function () {
  const query = MyCollection.find({},{fields: {data-1: 1, data-2: 1}});
  const handle = query.observeChanges({
    changed(id, fields) {
      $('.show').removeClass('show');
    }
});

Это предполагает, что существует коллекция с data-1 полей data-1 и data-2 которые вы хотите отключить. Если ваши data-1 и data-2 являются помощниками, которые выполняют некоторые вычисления, тогда вы можете захотеть подойти к нему с помощью Tracker на основе реактивных vars.

1

Большое спасибо за вашу помощь!

@Michel Floyd позволил мне понять, что моя проблема не вызвана чем-то, связанным с Meteor, а с помощью бутстрапа.

@Fred Stark добавил приятную вариацию решения, он использует автозапуск, который больше похож на Meteor, и он использует.collapse('hide') вместо.removeClass('show'), который дает некоторый хороший эффект затухания, по крайней мере, на IOS.

Поскольку я перепутал несколько вопросов, я уточню их один за другим:

Найти триггер: вы можете использовать autorun или observChanges, как было предложено, но оба они не нужны в конце, потому что всегда встречается помощник Meteor. Первая попытка:

<a href=# class='{{collapsed}}'

Template.genericCollapse.helpers({
  collapsed () {return "collapsed"},
})

Код в этом помощнике всегда будет работать, когда что-то в шаблоне изменится. Если данные-1 или данные-2 по какой-либо причине меняются, код будет исключен, так что это мой триггер.

Правильно используйте помощники: первая попытка не делает ничего на html, потому что пробел {{collapsed}} не изменяет его содержимое. Хотя вспомогательный код выполняется, возвращаемое значение не изменяется и, следовательно, не влияет на сторону html. Чтобы увидеть какое-либо изменение, возвращаемое значение должно быть различным каждый раз. Вторая попытка:

Template.genericCollapse.helpers({
  collapsed () {return "collapsed " + Random.Id()},
})

Ужасно, как я уже сказал, но, по крайней мере, он устанавливает правильный класс для a.

Избавьтесь от "шоу": И вот Мишель: Потому что "показать" в div контролируется Bootstrap, вы не можете контролировать это с помощью любого вида пробела/помощника, но с javascript. Третья попытка:

Template.genericCollapse.helpers({
  collapsed () {
    $('.show').removeClass('show');
    return "collapsed " + Random.Id()},
})

Это работает! Возможно, потребуется сузить ".show", если присутствуют другие элементы, имеющие класс "show", но это путь.

Prettify: наличие Random.Id() как класса по-прежнему плохое. Поэтому давайте относиться так же, как к обработанному div. Кроме того, мы должны использовать "uniqueId" в качестве идентификатора для обоих. Четвертая попытка:

Template.genericCollapse.helpers({
  collapsed () {
    $('[data-target="#uniqueId"]').addClass('collapsed');
    $('#uniqueId').removeClass('show');
    return "collapsed"},
})

Сделайте это блестящим: нет необходимости в помощнике {{collapsed}}, чтобы возвращать любое значение больше, все это делается с помощью javascript. Нам просто нужна функция триггера, так что это окончательный код:

<template name="genericCollapse">
  {{data-1}}
  <a href=# class='collapsed' data-toggle='collapse' {{hook}}
     data-target='#uniqueId'>Show/hide data-2</a>
  <div class='collapse' id='uniqueId'>
    {{data-2}}
  </div>
</template>

Template.genericCollapse.helpers({
  hook () {
    $('[data-target="#uniqueId"]').addClass('collapsed');
    $('#uniqueId').removeClass('show');
  }
})

Работает как шарм.

1

@Мишель Флойд прав насчет борьбы с бутстрапом.

Однако, поскольку вы сказали, что используете Session vars, просто используйте автозапуск:

Template.genericCollapse.onRendered(function() {
  this.autorun(() => {
    const data1 = Session.get('data-1');
    const data2 = Session.get('data-2');
    if (data1 === someCondition || data2 === someOtherCondition) {
      this.$('.collapse').collapse('show');
    } else {
      this.$('.collapse').collapse('hide');
    }
});

При каждом изменении data-1 или data-2 эта функция будет повторно запущена

  • 0
    Это правильный ответ для сессионных / реактивных переменных.
0

Вы можете сделать это методом метеор, возвращая класс к элементу из помощника:

шаблон:

<template name="genericCollapse">
  {{data-1}}
  <a href=# class={{isCollapsed}} data-toggle='collapse'
     data-target='#uniqueId'>Show/hide data-2</a>
...
...
</template>

Helper:

Template.genericCollapse.helpers({

isCollapsed: function(){

    if()// logic to check if it needs to be collapsed
       return "collapsed"
    else
       return "collapse"
    }
});

Ещё вопросы

Сообщество Overcoder
Наверх
Меню