В части 1 мы рассмотрели, как использовать преимущества динамического рендеринга компонентов, чтобы отделить содержимое информационных панелей от самой информационной панели. В этой части мы рассмотрим, как добавлять / удалять элементы из дорожек, как выполнять вызовы служб для отдельных карточек на панели инструментов и как реализовать перетаскивание при сохранении состояния.

Добавление и удаление элементов

Прежде, чем мы начнем

Лучшая практика в Angular - переместить общее состояние в службы, которые могут использоваться несколькими компонентами вашего приложения. Поскольку мы объявили наши треки в файле dashboard.component.ts, он недоступен напрямую для любого другого компонента, включая содержимое панели мониторинга. Чтобы иметь возможность добавлять или удалять карточку из любого места, кроме самого компонента приборной панели, нам нужно будет переместить переменную track в сервис.

Прежде чем мы продолжим, важно, чтобы вы понимали концепцию наблюдаемых сервисов. Наблюдаемые сервисы - это обычные сервисы, которые возвращают данные, обычно состояние, в форме наблюдаемых. Если вы плохо знакомы с концепцией наблюдаемых сервисов и с преимуществами / недостатками, с которыми они связаны, я рекомендую вам прочитать эту статью, которая освещает эту тему более подробно. На данный момент это позволит нам поделиться состоянием панели инструментов, что скоро будет полезно.

Сначала сгенерируйте сервис информационной панели. Затем скопируйте массив треков из dashboard.component.ts в свой сервис. Я также переименовал переменную в defaultState.

dashboard.service.ts

Во-вторых, создайте тему, по которой мы можем предоставить данные. Субъект похож на EventEmitter с возможностью иметь несколько наблюдателей. В нашем случае мы хотим использовать BehaviorSubject. BehaviorSubject будет передавать последнее заданное значение новым слушателям. Мы можем создать наблюдаемый объект из нашего объекта, вызвав this.subject.asObservable (), я назвал эту переменную track $.

dashboard.service.ts

Наконец, извлеките треки из службы в компоненте приборной панели.

dashboard.component.ts

Теперь мы можем приступить к добавлению и удалению треков с панели управления.

Удаление предметов

Чтобы удалить элементы, создайте метод в службе панели инструментов, я назвал его removeItem. Удаленный элемент будет принимать элемент в качестве параметра и пытаться удалить элемент из состояния треков и передать изменения в тему.

Чтобы получить состояние из темы, вызовите subject.getValue (). Это даст нам снимок объекта на тот момент времени. Теперь, когда у нас есть снимок, мы можем начать манипулировать им.

dashboard.service.ts

Удалите элемент, перебирая каждую дорожку в массиве состояний. Затем для каждой дорожки перебирайте элементы на дорожке. Если элемент в цикле соответствует элементу, указанному в качестве параметра, мы хотим вырезать его из дорожки. Как только это будет завершено, мы хотим снова передать новое состояние субъекту, вызвав this.subject.next ().

dashboard.service.ts

Добавление предметов

Создайте метод с именем addItem, который возьмет элемент и добавит его на одну из дорожек. Я решил протолкнуть новый элемент на дорожку с наименьшим количеством элементов. Необязательно: вы можете проверить, что элемент не существует ни на одной из дорожек, прежде чем добавлять элемент, чтобы предотвратить дублирование.

dashboard.service.ts

Прежде чем мы сможем использовать методы addItem / removeItem, мы должны обсудить, как выполнять вызовы отдельных служб из содержимого панели мониторинга, что рассматривается в следующем разделе.

Вызов служб и передача состояния в содержимое панели мониторинга

Отделение состояния содержимого от панели управления - чрезвычайно эффективный инструмент. Это позволяет нам независимо создавать контент панели мониторинга, представленный в виде карточек, без какой-либо конкретной логики контента в компоненте панели мониторинга. А если вы работаете в корпоративной среде, отделение панели мониторинга от состояния содержимого позволяет нескольким организациям создавать, управлять и поддерживать содержимое панели мониторинга, за которое они несут ответственность, без необходимости касаться самого компонента панели мониторинга. Например, финансовый отдел может захотеть создать финансовую карточку, чтобы показать финансовые вещи. Когда они это сделают, им не придется ничего трогать, кроме dashboard-cards.enum.ts и dashboard-cards.ts.

В этом примере создайте еще одну службу под названием HelloService. Эта служба будет содержать список имен, который будет извлекаться из содержимого панели управления. Кроме того, добавьте имя Input () в HelloWorldComponent и отобразите его в шаблоне компонента.

hello-world.service.ts

hello-world.component.ts

hello-world.component.html

Если вы следуете руководству, вы должны создать компонент HelloWorldContainer в первой части. Контейнер должен вызвать службу, получить необходимую информацию и передать ее содержимому через свойства Input () дочернего компонента.

Из-за того, как мы сопоставляем контейнеры для отслеживания элементов, на панели управления должен быть контейнер для каждого уникального элемента. Это связано с тем, что контейнеры должны вызывать службы для получения данных, и в зависимости от того, как вы структурируете свои компоненты, это может ограничить возможность повторного использования любого конкретного контейнера.

Чтобы получить другие данные, я создам второй контейнер hello-world-two.container.ts и добавлю его к entryComponents, что является тем же процессом, который мы использовали для hello-world.container.ts.

Каждый контейнер будет получать имя из HelloService и передавать его в HelloWorldComponent. Единственное отличие - это имя, которое извлекает каждый контейнер.

hello-world.container.ts и hello-world-two.container.ts

Теперь перейдите в dashboard-cards.ts и dashboard-cards.enum.ts и добавьте еще одну запись, HELLO_WORLD_TWO.

dashboard-cards.ts

dashboards-cards.enum.ts

В dashboard.service.ts измените компонент второго элемента на «HELLO_WORLD_TWO».

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

Ура!!! Теперь мы создали независимую статическую панель управления. В следующем разделе мы сделаем контент перетаскиваемым.

Реализация перетаскивания

Перетаскивание - обычно довольно сложная, но рутинная задача. К счастью, ng2-dragula делает это очень просто. Идите и установите его. пряжа добавить нг2-драгула. В репозитории dragula есть список инструкций по установке, которым вы должны будете следовать. Dragula также необходимо будет импортировать в модуль панели инструментов.

Чтобы реализовать перетаскивание, все, что нам нужно сделать, это добавить директивы dragula и dragulaModel вместе с событием dragulaModelChanged. Директива dragula просто определяет, к какой группе должна принадлежать данная дорожка. В нашем случае они оба принадлежат к группе панели мониторинга. Директива dragulaModel указывает, какие элементы должна содержать дорожка перетаскивания. Это будет синхронизировано с данными наших треков. Также есть некоторые css, которые нам понадобятся, чтобы гарантировать, что, когда дорожки пусты, дорожка не сжимается до нулевого размера, поэтому мы можем перетащить материал обратно.

dashboard.component.html

dashboard.component.scss

С этими дополнениями карты теперь можно перетаскивать. Потрясающие! Теперь приступим к сохранению некоторого состояния.

Состояние хранения

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

Во-первых, мы должны взять измененное состояние, вызванное событием dragulaModelChanged, и установить его в службе. Нам понадобится метод, чтобы взять все состояние дорожек и вставить их в объект. Добавьте метод с именем setState в DashboardService. setState требует массив треков и соответственно устанавливает состояние.

dashboard.service.ts

Мы назовем это в компоненте приборной панели, когда треки будут изменены.

DragulaModelChanged будет генерировать событие, которое возвращает массив, переданный в dragulaModel, с соответствующими изменениями после перетаскивания. Загвоздка в том, что он возвращает только отдельные элементы конкретного трека, а не массив треков. Это означает, что нам нужно будет знать, какие элементы трека меняются. Для этого мы можем легко добавить ссылку на указатель в цикле треков ngFor в шаблоне панели инструментов. Это даст нам ссылку на трек, на который ссылается dragulaModelChanged.

Создайте метод с именем changed в компоненте панели инструментов. Измененный метод будет принимать трек и trackIndex. После того, как вызывается измененный, он извлекает текущее состояние и применяет изменения, данные нам из события. Если у вас есть ссылка на измененное состояние, передайте ее в setState, чтобы обновить службу.

dashboard.component.ts

Теперь мы можем добавить событие dragulaModelChanged в наш div и изменить вызов.

dashboard.component.html

И вот здесь все становится странно. Поскольку мы обновляем объект, который диктует, что должно быть отрисовано, мы должны указать детектору изменений, чтобы он проверял наличие изменений, и только после этого мы перезагружаем контент. Если вы сделаете это в неправильном порядке, метод loadContents не будет иметь правильный набор ng-шаблонов для рендеринга компонентов. Лучшее место для добавления вызова detectChanges - это подписка на треки. Эта подписка вызывается всякий раз, когда объект в службе панели инструментов получает новое значение, что в нашем случае будет при перетаскивании карточек.

dashboard.component.ts

Ура, пока мы тащим, состояние стабильное !! Осталось только сохранить состояние.

Сохранение состояния панели мониторинга

Сохранить состояние приборной панели очень просто. Все, что нам нужно сделать, это сохранить треки приборной панели в локальном хранилище (или в любом другом месте) и загрузить его при запуске. Мы также реализуем конфигурацию по умолчанию на тот случай, если пользователи впервые заходят на панель управления.

Создайте в службе панели мониторинга метод с именем loadFromLocalStorage. Это подтянет состояние панели управления и обновит службу.

dashboard.service.ts

Создайте другой метод; saveTracksToStorage. Это соответствует названию и сохраняет треки в локальном хранилище в виде строки.

dashboard.service.ts

Чтобы сохранить обновления треков в будущем, подпишитесь на треки $ в конструкторе сервиса панели инструментов. Прежде чем это произойдет, нам нужно убедиться и вызвать this.loadTracksFromStorage, чтобы получить последнее сохраненное состояние.

dashboard.service.ts

И бум!

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

Исходный код: https://stackblitz.com/github/buttars/enterprise-dynamic-dashboard/tree/part-2

Надеюсь, вам понравился этот цикл из двух частей. Если бы вы это сделали, я был бы очень признателен, если бы вы дали ему несколько хлопков. (50 - максимум, если вы чувствуете себя очень щедрым).

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