Клуб API Карт

ObjectManager, балун кластера и загрузка данных по требованию

Пост в архиве.

Здравствуйте. Столкнулся с проблемой. На карте имеется несколько тысяч точек, добавленных при помощи objectManager. Включена кластеризация. При клике на точку выполняется AJAX-запрос данных, после чего загруженные данные добавляются к геообъекту

objectManager.objects.events.add('balloonopen', function(e) {
  var objectId = e.get('objectId');
  var hasBalloonData = function(objectId) {
    return objectManager.objects.getById(objectId).properties.loaded;
  };

  if (!hasBalloonData(objectId)) {
    // getPointInfo - это AJAX-запрос данных метки
    getPointInfo([objectId]).done(function(response) {
      var obj = objectManager.objects.getById(objectId);
      $.extend(true, obj.properties, response);
      obj.properties.loaded = true;
      _map.balloon.setData(obj);
    });
  }
});

Но иногда возникает ситуация, что две точки имеют одинаковые координаты и остаются объединенными в кластер до максимального масштаба. В этом случае при клике на кластер вызывается балун кластера.

Я хочу оставить двухколоночный макет, но в правую часть выводить данные в виде кастомного макета метки, такого же, как и при клике на одиночную метку. Данные должны подгружаться так же аяксом.

Все в целом работает, данные подгружаются, но балун не меняет своего внешнего вида. И выглядит пустым (см. картинку). Каким образом добавить название метки в левую часть? Как сделать так, чтобы правая часть балуна обновлялась сразу же, а не после переключения между точками?

UPD:

Получилось сделать только так:

getPointInfo(ids).done(function(response) {
  $.each(response, function(idx, pointInfo) {
    var obj = objectManager.objects.getById(pointInfo.id);
    $.extend(true, obj.properties, pointInfo);
    obj.properties.loaded = true;
    obj.properties.clusterCaption = pointInfo.title;
  });

  var balloonData = objectManager.clusters.balloon.getData();
  objectManager.clusters.balloon.setData(balloonData);
});

Это правильный способ обновления содержимого балуна? Или можно то же самое сделать более правильно?

9 комментариев
То как это делается сейчас в примере в песочнице – не лучший способ. Мы наверное его исправим в ближайшее время.



Правильнее использовать для этого макет.
Проще собирать и обновлять данные объектов, не вызывая каждый раз эту колбасу objectManager.objects.getById(...), и не нужно слушать событие "balloonopen", – перестроение макета можно делать простым вызовом rebuild на макете
Так же не нужно использовать костыль geoObjectOpenBalloonOnClick: false
и самому открывать балун "ручками"


пример
http://jsfiddle.net/1dpotvy6/
dimik,


Спасибо за ответ. Не копал в эту сторону.
У меня вопрос, а как clusterCaption тоже получать аяксом? Или правильнее его сразу писать? Просто хотелось бы минимизировать количество начальных данных, требуемых для инициализации всего массива меток.
denis.ezhkov,
в своем макете можно использовать любое поле. В стандартных макетах это поле используется как в списке (сайдбар слева) так и в контенте справа.


Вы можете не показывать стандартный макет, пока  clusterCaption не будет получено для всех меток в кластере, а показывать что-то другое (прелоадер).
dimik,
спасибо, все прояснилось :)
dimik,
Подскажите пожалуйста, скопировал ваш пример в свой код, у меня при первом клике балун не открывается, только при втором. Как сделать так, чтобы балун открывался при первом клике?
Обновлено 7 августа 2018, 12:59
dimik,
 Полностью скопировал пример на localhost, ничего не меняя, всё равно при первом клике ничего не происходит.
Борис,
Да, это старая ошибка в макете кластера, которая до сих пор не исправлена. Там был какой-то воркэраунд из двух строчек, надо загружать макет явно, перед созданием кластеризатора. Я к сожалению не смог его найти, автор удалил этот пост. Напишите разработчикам, они должны помочь
dimik,
Понял, спасибо за ответ и за пример, напишу в тех. поддержку. Кстати, если в jsfiddle переключить Language  с Babbel + JSX на JavaScript, то ошибка воспроизводится (при первом клике ничего не происходит).
dimik,
 Вот, что ответили в тех. поддержке: 
"Временным решением будет добавить openEmptyBalloon: true у кластера http://jsfiddle.net/sjhtyLvu/"