Всем привет!
В прошлой статье мы рассмотрели один из таких фундаментальных аспектов LWC компонентов как реактивность, который позволяет нам создавать максимально быстрые и отзывчивые пользовательские интерфейсы. В этой статье мы продолжим изучение LWC компонентов, в частности затронем такую немаловажную тему как взаимодействие компонента с апекс.
Существует два подхода для получения данных из апекс: реактивный (сервис @wire) и императивный. Рассмотрим сперва реактивный подход, так как он имеет несколько интересных свойств.
Для того, чтобы дать возможность сервису wire общатся с апекс — необходимо выполнить следующие действия:
1.Импортировать wire в JS контроллере, это позволит использовать реактивные сервисы в вашем компоненте.
2.Следующим шагом необходимо создать Apex класс, который будет находится на стороне бэкенда в вашей сейлсфорс организации. Касательно класса — все довольно просто: он должен быть с модификатором доступа public, чтобы компонент имел доступ к нему. Методы, которые объявлены в нем, должны быть static и иметь аннотацию @AuraEnable для того, чтобы сделать их видимыми для LWC компонента. Стоит оговориться, что это утверждение истинно только для методов, которые вы хотите непосредственно вызывать из вашего компонента; другие методы не обязаны иметь данных ограничений.
3.Последним шагом является импорт ваших вызываемых методов из Apex класса в JS контроллере. В данном примере getContacts является алиасом, по которому мы будем обращаться для вызова метода из Apex. Строка, идущая после ключевого слова from, является путем до вашего метода, с указанием самого класса и имени метода.
После того, как будут пройдены все вышеуказанные шаги, мы можем использовать wire для получения данных из SF.
Давайте попробуем вызвать реактивный сервис на следующем примере. Представим ситуацию, в которой мы хотим получить данные о контакте (существующем в SF) на основе введенной пользователем информации.
Особенностью сервиса wire является то, что он поддерживает реактивные переменные: переменные, которые начинаются с префикса $. Если состояние переменной изменится, метод, помеченный аннотацией wire, отработает еще раз и повторно визуализирует компонент.
Создадим компонент и назовем его “searchComponent”:
1.searchComponent.html:
В html разметке создадим стандартный инпут, в который будем вводить имя, по которому мы будем производить поиск внутри нашей Salesforce организации, а также выведем полученные данные в разметку. На инпут установим onblur ивент, который будет срабатывать в момент, когда пользователь закончит ввод и нажмет на любое пространство вне инпута.
2.searchComponent.js.
В Js контроллере создадим переменную searchKey, которая будет хранить в себе значение, введенное пользователем. Метод handleChange() — это обработчик ивента, который устанавливает введенное значение в переменную searchKey. Объект contact, помеченный @track аннотацией, будет хранить в себе возвращенные апексом данные.
Давайте подробней остановимся на методе, помеченном аннотаций @wire. Для того, чтобы вызвать реактивный метод, мы обращаемся к импортированному ранее методу из апекс по getContacts алиасу.
Параметр contactName — это параметр, который будет принимать в себя вызываемый нами апекс метод. Как видите, мы передаем в этот атрибут переменную searchKey с префиксом $. Это дает компилятору понять, что эта переменная реактивна и при изменении ее значения необходимо повторно запустить метод @wire. Вложенный метод getData() представляет собой данные, которые нам вернет наш апекс метод. Data это, собственно, те данные, которые будет возвращать апекс с помощью ключевого слова return , error вернет ошибку (если такая будет), возникшую при работе апекс метода.
Теперь давайте взглянем на сам апекс метод.
Метод принимает в себя имя, введенное пользователем, и делает по нему SOQL запрос, после чего возвращает нам JSON строку в JS контроллер. Стоит оговориться, что существует несколько способов передачи данных в JS контроллер, но конвертирование данных JSON генератором является одним из самых быстрых и удобных.
После того, как мы вернули данные в JS контроллер, — парсим их в объект contact стандартным JSON парсером.
После всего этого можем взглянуть на конечный результат. После того, как мы введем имя в инпут поле, состояние переменной searchKey изменится, а так как в сервисе @wire она помечена префиксом $ — произойдет повторное обращение в апекс, и мы получим новые данные.
Wire сервис является очень быстрым и удобным, что позволяет нам создавать отзывчивые приложения, но все же он не лишен недостатка. Что было бы, если мы захотели с помощью wire, например, произвести какую-нибудь DML операцию, к примеру вставку контакта? Мы получим ошибку LimitException: Too many DML statements: 1. Причина кроется в том, что вызов wire не поддерживает DML операции, поскольку значение переменной может меняться слишком часто. Этим могут воспользоваться злоумышленники и нарушить корректную работу сервера, написав скрипт, который будет бесконечно менять состояние переменной и, как следствие, делать недопустимое количество DML операций.
Здесь нам на помощь приходит Императивный метод взаимодействия с апекс. Он не поддерживает реактивный вызов метода как wire, его придется запустить принудительно, — но он способен производить DML операции. Синтаксис вызова метода императивно почти идентичен вызову wire метода. Давайте попробуем вставить контакт, используя императивный подход.
1.Немного модифицируем разметку, добавим в нее 3 инпут поля. А также кнопку Save Input, по нажатию на которую будет происходить вставка нового контакта.
2.Далее создадим простой аппекс метод saveContact для вставки контакта. Он принимает в себя три параметра, на основе которых создает контакт. Стоит сразу оговориться, что при наличии большого количества параметров удобнее будет сформировать из них объект, а потом передать его в аппекс. После чего можно будет его распарсить.
3.И в заключении модифицируем JS контроллер, добавив обработчики для новых инпут полей. А также добавим метод saveContact, который будет стучаться в апекс класс. Для этого импортируем его и добавим этот метод как обработчик события кнопки Save Input.
Как вы могли заметить, метод saveContact принимает в себя три параметра, после чего передает их в апекс метод и производит вставку нового контакта. Так же как и wire, он способен возвращать какой-то результат, но в данном случае это нам не пригодилось, поэтому блок then, в котором мы можем получить возвращенные данные, пуст.
Давайте взглянем на конечный результат.
Как можно увидеть, мы императивно вставили контакт, а после успешно реактивно вытянули его APEX.
Таким образом, давайте подведем некую черту под всем вышесказанным. Нам стоит использовать реактивный подход в ситуациях, когда необходимо динамически получать данные при изменении состояния переменной. Императивный подход следует использовать тогда, когда нужно производить какие-либо DML операции или же иметь строгий контроль над вызовом апекс методов.