Клуб API Карт

Обновление списка ListBox по событию

Пост в архиве.
Добрый день! Бьюсь над задачей, не могу решить самостоятельно. Прошу помощи!

Есть свой элемент управления ListBox с собственным макетом выпадающего списка. В списке слои, которые показываются при выборе элемента списка.

Сейчас пока что список - это просто массив в items: listBoxItems.

Но мне бы хотелось динамически обновлять список при перемещении и зумировании карты (boundschange). Я написал некую функцию, которая получает список карт в формате JSON от серверного скрипта.

Вопрос, как мне прикрутить обновление списка карт при событии boundschange? При загрузке карты список так же должен динамически обновляться.
28 комментариев

ListBox расширяет интерфейс ICollection у него есть методы add и remove

У меня возникли сложности. Не могли бы Вы показать примерно как мне решить мою задачу... Буду очень признателен.

Сложности с чем?
Слушаете boundschange на карте,
запрашиваете на сервере новый список слоев,
обновляете listBox

Слушать умею, с добавлением поигрался - вроде бы всё работает, спасибо.

Вопрос первый: правильно ли я понимаю, что сначала нужно удалять перебором все элементы списка, или есть какой-то метод, очищающий список?
Вопрос второй: как мне изначально при загрузке карты создавать список, который будет заполнятся списком элементов по запросу?
Наверное, поторопился с вопросом № 2, справился с ним сам.

Что за "слои" у вас? Если это именно инстанции ymaps.Layer, то лучше использовать TypeControl вместо listBox.

Слои с пользовательскими картами, накладываются поверх стандартной карты.

Лучше использовать TypeControl

Вероятно, Вы имели ввиду typeSelector? А я могу добавить второй в дополнение к стандартному выбору карт? При этом элементы списка нужно будет формировать динамически (событие boundschange), потребуется нацепить свой макет выпадающего списка, и возможно, в будущем потребуется нацепить также и макет для элементов списка. Всё это возможно?

И чем в этом случае typeSelector использовать лучше listBox?

Да, TypeSelector, он как раз для смены типов карты (наборов слоев),

да, можно свой макет, как в листбокс.

http://dimik.github.io/ymaps/examples/controls/typeselector/

 

Слои объединяются в типы (можно комбинировать свои и стандартные) и добавляются в TypeSelector

 

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

1. Спасибо, я обязательно попробую TypeSelector, но тогда ещё вопрос на эту тему: можно ли хранить в слое с картой свои свойства и как обращаться к ним? К примеру, мне нужно центрировать текущую область видимости карты по многоугольнику. Сейчас я слушаю select на элементе ListBox, и цепляю setBounds, а в качестве координат для центрирования беру свойство из data.get(). Как мне решить эту же задачу через TypeSelector?

2. Своё имя для TypeSelector проще устанавливать через макет выпадающего списка?

1. Можно хранить в поле data

2. Имя передается первым параметром в конструктор типа карты, никаких имен в макетах хранить не надо

У меня получилось сделать всё, что Вы мне советовали. Но при выборе карты в своём TypeSelector она устанавливается вместо выбранной карты в "Слоях", а мне нужно её накладывать поверх в виде слоя. Как это сделать? Я понимаю, что их можно комбинировать, но при этом выбор основной карты должен оставаться возможным.

При создании своего типа карты Вы передаете ключи слоев, в том числе можно передавать ключи стандартных, например, схема "yandex#map"

По определённым соображениям был вынужден вернуться к использованию ListBox. Как мне удалять все пункты меню?  Перебором? А каким образом?

Пытался так, но удаляются не все почему-то пункты:

        listBox.each(function (i) {
            listBox.remove(i);
        });
Ха, в API 2.0 есть removeAll() и он к счастью работает!

Но почему-то этот метод не описан в API 2.1, но описан в API 2.0. У Яндекса есть ответ на этот вопрос?

Скажите, пожалуйста, ещё вот что.

Я выбираю пункт в моём ListBox. Но после смены масштаба или центра карты происходит удаление всех дочерних элементов списка. При этом выбранный пункт не прикрепляется к такому же добавленному пункту. Нужно либо не удалять выбранный пункт (и не добавлять его снова после получения новых элементов списка), либо после удаления и получения нового списка элементов прикреплять выбранный дочерний элемент...

Помогите выбрать правильное решение.

Помогите, пожалуйста, в какую сторону копать по последнему вопросу?

Что значит "не прикрепляется"

Не очень понимаю в чем суть

removeAll() удаляет все элементы ListBox, включая выбранные элементы списка. Получается, что уже не получится нажать пункт списка снова, чтобы скрыть карту.
Возможное решение - не удалять выбранный пункт. Пытался сделать так:


for (item in listBox.getAll()) {
    if (listBox.getAll()[item].state.get('selected') == true) {
        console.log(listBox.getAll()[item].data.get('content'));
        listBox.remove(item);
    }
}

Но не работает - ошибка. Если убрать listBox.remove(item); то имя выбранной карты выводится как и полагается при перемещении карты или изменении масштаба.

Вы удаляете элементы, перебирая их, это все равно, что пилить сук под собой

Тогда как быть, чтобы не удалять выбранный элемент?

Лучше удалять и добавлять заного

Хорошо, я всё удалил... Как мне теперь скрывать слой с картой, если пункта меню, который это делает, больше нет?

не понимаю в чем именно проблема. У вас есть состояния пунктов (selected/not selected) эти состояния можно хранить, например, в state контрола, при добавлении пункта выставлять ему состояние (если было сохранено), при удалении сохранять текущее состояние

Я не понял, как сохранять состояние пункта, если новые пункты добавляются через new ymaps.control.ListBoxItem(). Это уже другие пункты совсем получаются... Или я правда что-то не так понимаю.

Что мешает хранить в state свой объект с полями _itemId_: _itemState_

Оо, спасибо за помощь , я сделал, правда совсем иначе, но всё работает как надо.