Как правильно связать сервисы объектами для которых он создается?
Опять... Переопределил я директиву и понял, что теперь мне хочется добавить управление (пауза-плей).
И вот теперь я рассматриваю эту директиву, как часть или даже основную часть объекта-компонента video-bg-player.
И ещё я захотел на кнопки повесить анимацию и сделать их при помощи самого angular и его анимации ( это пока, а потом возможно что-то посильнее придется тянуть). И вот вроде такая мелочь, как анимация все и поломала.
Если перейти в ооп измерение и поставить себе цель сделать легко поддерживаемое и расширяемое приложение, то первое что приходит в голову, это инициализация в одном месте и инжектор. Далее понимаешь, что "мой мега плеер" это одна большая "MainVideoBgView", которая и расставляет сам плеер и его кнопочки по нужным местам, которые она либо сама и создает, либо в неё инжектят, ну или берет их из ассет-манагера. Теперь начинаю понимать, что кнопка это объект, который я передаю в класс, который будет её анимировать по вызову метода play. Как я его туда передаю? Ну тут только два способа либо инжектю из места где собираю все приложение, либо мое главное представление, которое так же может являться местом инициализации, передает в класс анимации объект кнопку при его создании.
Все просто, но с angular все немного сложнее. Здесь mainView является директива, а кнопка вообще по сути не является объектом который будет создаваться ею и тем более её (кнопку) нельзя инжектировать.
Можно создать сервис для анимации и в него передать сервис $document и уже самому там искать то что нужно, но это совершенно не правильно. Есть ещё другой вариант, что директива передаст ссылку на кнопку в этот сервис, но это хоть и правильно, но выглядит убого и некрасиво. Некрасиво в плане что сервис стоит и ждет пока в него кнопку передадут, а потом ещё несколько сервисов нужно писать которые будут проверять, а есть ли эта кнопка или нет. Можно и не проверять, но это будет неправильно.
Но есть способ, когда директива будет играть роль настоящего MainView и передаст не в сервис, а уже в обычный класс при его создании в своем чреве, кнопку полученную из своей скопы, а не лазая и ища по чужим.
Но как это с точки зрения angular, ведь придется не только кнопку передавать, но ещё и $animate и прочее?
Или я не могу приспособится к angular и есть другой способ? Вот как бы Вы сделали тоже самое?
это идет в разрез с идеей директив. Вы не должны вообще делать выборки элементов за пределами шаблона вашей директивы, ангуляр сам вам все найдет и подключит, через контроллеры директив если у вас прописаны зависимости.
В идеальном мире ваша директива делалась бы примерно так:
Далее магия ng-transclude и общение через контроллер директивы, что позволяет нам реализовать свои контролы и т.д. Так же можно реализовать делегаты для директивы через сервисы или через колбэки директив.... Как пример - можете посмотреть как это реализовано в ionic framework (UI фреймворк для мобильных приложений на angular)
Пока я понял только одно, что моя директива, которая находится пока в голове, приблизительно совпадает с Вашей. Я уже закрыл редактор и только потом понял одну истину, что если я хочу получить в одной директиве вложенные элементы, то эти элементы обязательно должны быть директивами. Ведь в директиве, пока я не читал о ng-transclude, есть возможность получить вложенные элементы в методе link в параметре element. Но если представить что я хочу получить две кнопки которые лежат в индексированном массиве, то мне нужно обязательно соблюдать последовательность. Типа var a = element[0] var b = element[1]. И это приводит к тому, что добавь я ещё один элемент по верх уже имеющихся, то a и b ссылались бы не на те элементы. Хоть по какому-то id можно найти только через element.find, который ищет по имени тега, что в свою очередь означает что даже для одной кнопки нужно писать директиву. Что и не так уж и плохо.
Но сегодня я уже не осилю, а завтра прочту о ng-transclude, пойму что это такое, а потом если что ещё спрошу.
vasIvas: родитель ничего не должен знать о своих детях (ну то есть как, может, и иногда это надо, но обычно дети сами сообщают). Вот у детей будет ссылка на контроллер родителя если вам того будет угодно. И так можно будет уже организовывать взаимодействие.
Сергей Протько: такой вариант тоже знаю, но забыл, ведь это вторая проблема после анемичной модели - тонкое и тупое представление. Самое интересное, что в представлении у Вас событийная модель выступает в роли гаранта низкой связанности, но в модели Вы её полностью отвергаете. А вот то что родитель собственных детей не может приструнить-удалить из себя, это нормально.. Тогда что же такое контроллер? Ведь если представление не должно знать о своих детях, то только контроллер может их удалить. Получается что контроллер просто божественный объект, который делает все.
Хотя то что дети посылают события, это так и должно быть, ведь еще баблинг.
Вы пробовали когда-нибудь писать игры на canvas? Я это к тому, что Вы работает все в том же js и все та же парадигма mvc, но только и наверное ТОЛЬКО в таком положении можно понять что такое mvc, ведь html и css уже не будет и сразу окажется что mainView начнет создавать други mainElementView и не скажешь что это ненормально.
Это композитное представление называется. А ещё бывает и в моделях делают баблинг, да и в контроллерах. Хотя я опять немного ошибся, ведь можно послать событие removeMe и родитель удалит таргет. А вот токая же история с добавлением в класс анимации не прокатит, нужен тип iанимтный. Хотя можно в константу тип вбить и на него проверять.. Как много вариантов..
vasIvas: Вы о чем? В контексте директив событийной модели особо нету, ну то есть если не касаться отдельных случаев вроде инпутов и т.д. но это уже особенности реализации конкретных директив. Если вам надо послать событие с учетом балбинга - у вас есть скоуп, через него и эмитте события. Собственно ангуляр так и делает, когда вы закончили с родителем, вниз по дереву уходит событие $destroy и все дети его получают и уничтожают себя (например отключают листенеры которые навесили на $document к примеру)
Директива родитель никого не удаляет сама по себе, она в большинстве случаев даже не знает что у нее есть дети (а лучше считать что никогда не знает, ибо не должна, иначе мы нарушаем изоляцию), они могут быть, их может не быть, удалять их оно не имеет право (не оно породила - ни ей уничтожать). Ни контроллер, ни что вообще не может взять и приказать ребенку удалиться - у них даже ссылок на них нет.
По сути общение директив происходит исключительно между контроллерами, то есть контроллер одной директивы ничерта не знает о view другой, да и не должен. Это обязанность контроллера как медиатора - организовывать общение различных частей системы, не больше. Ну а если у вас контроллер делает все - это исключительно ваша проблема.
директивы должны общаться только снизу вверх, сверху мы можем только послать ивент всем через скоуп, или же поменять данные. Приказать что-то вниз мы не можем и не должны.
vasIvas: что до вашей проблемы с анимациями и прочим - в моем предложении это решается чуть более чем просто - заменяете реализацию директивы контролов на свою, с анимациями.
Сергей Протько: про баблинг в моделях... А Вы когда Вам нечего будет делать, просто ради интереса подумайте как бы Вы сделали тротегию на canvac без сервера. Вот чтобы в игру можно было играть без сервера.
vasIvas: я не играюсь и не делаю игрушки. Потому мне сложно это представить. И да, насколько я понимаю вы ведете разговор о реактивном программировании, ивент стримах и т.д.