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

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

В Lightning Experience мы добавили функцию «Мастер продаж», созданную поверх Lightning Flow и доступную через вкладку. Каждый шаг сбора данных выполняется с помощью элемента Flow Screen, который инкапсулирует компонент Lightning.

Если вы не знакомы с использованием Lightning Component и Flow, ознакомьтесь с дополнительными сведениями на странице https://developer.salesforce.com/docs/atlas.en-us.lightning.meta/lightning/components_using_flow.htm.

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

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

В нашем приложении есть несколько компонентов Lightning, которые содержат формы с различными полями для заполнения. Пользователю необходимо прокрутить страницу, чтобы добраться до полей, которые находятся в нижней части формы, а некоторые полезные кнопки действий доступны только в нижней части представления.

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

Итак, мы начали искать решение, но, к сожалению, нет способа деактивировать «потяните для обновления». Эта функция включена в мобильную версию Salesforce, и существует множество причин, по которым ее нельзя деактивировать.

Например, «вытягивание для обновления» полезно, когда вам нужно обновить данные или когда вам нужно получить новые поля, которые были добавлены к объекту.

Тогда мы подумали о том, чтобы сделать домашнее решение! А как насчет старого CSS-трюка и щепотки JavaScript? Как насчет двух вложенных контейнеров с фиксированным положением, чтобы сделать внутренний контейнер прокручиваемым?

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

// MyComponent.cmp
<aura:component implements="lightning:availableForFlowScreens" access="global">
  <div aura:id="mainContainer" class="mainContainer">
    <div class="childContainer">...</div>
  </div>
</aura:component>

mainContainer, окаймленный красным цветом, используется в качестве оболочки вокруг childContainer, окаймленного цвет морской волны. Магия достигается с помощью нескольких правил CSS, как показано в таблице стилей ниже.

// MyComponent.css
.THIS.mainContainer {
    background-color: transparent;
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    bottom: 60px; /* compensation for the navigation bar */
    border: 3px solid red; /* used to highlight border */
}
.THIS .childContainer {
    background-color: lightgray;
    position: absolute;
    top: 70px; /* compensation for the navigation bar */
    left: 10px;
    right: 10px;
    bottom: 10px;
    overflow-y: auto;
    border: 3px solid lightseagreen; /* used to highlight border */
}

К настоящему моменту вы получили прокручиваемый контейнер, в который можно поместить все необходимые элементы пользовательского интерфейса. Но этого не достаточно! На самом деле, если вы протестируете компонент, полученный здесь, в мобильной версии Salesforce, вы обнаружите, что функция «потяните для обновления» все еще работает.

Если вы когда-либо исследовали Aura Framework (ядро Lightning Component Framework), вероятно, вы сталкивались с компонентом, который обрабатывает события прокрутки для страниц. Этот компонент отвечает за обработку события touchmove (узнайте больше об этом событии), когда оно инициируется над оболочкой прокрутки страницы.

Нам нужно предотвратить распространение этого события за пределы нашего Компонента, поэтому нам нужно использовать mainContainer в качестве «стены» для всплытия событий.

Что такое пузырьковое событие? https://javascript.info/bubbling-and-capturing

// MyComponentRenderer.js
({
    afterRender: function (component, helper) {
        this.superAfterRender();
        var targetEl = component.find("mainContainer").getElement();
        targetEl.addEventListener(
            "touchmove", 
            helper.scrollStopPropagation, 
            true // we use capture!
        );
    }
})

В ресурсе Renderer нашего Компонента мы добавляем прослушиватель событий в mainContainer, который обрабатывает событие touchmove, вызывая метод scrollStopPropagation метод, объявленный в вспомогательном ресурсе.

Вы заметили, что здесь мы использовали метод addEventListener с параметром useCapture со значением true. Но что это значит?

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

Подробнее читайте по ссылке: https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener

Таким образом, мы блокируем распространение события после того, как событие будет впервые захвачено.

// MyComponentHelper.js
({
    scrollStopPropagation: function(e) {
        e.stopPropagation();
    }
})

В вспомогательном ресурсе мы объявили метод scrollStopPropagation, даже если он просто выполняет «stopPropagation» события. Метод объявлен за пределами области обратного вызова addEventListener только для повторного использования, если вам когда-нибудь понадобится повторно включить «потяните для обновления».

Фактически, вы сможете повторно активировать эту функцию, просто удалив только что добавленный прослушиватель событий.

// MyComponentController.js
({
    reactivatePullToRefresh: function(component, event, helper) {
        var targetEl = component.find("mainContainer").getElement();
        targetEl.removeEventListener(
            "touchmove", 
            helper.scrollStopPropagation, 
            true
        );
    }
})

Ограничения

Существуют некоторые ограничения, которые вы должны учитывать, прежде чем применять это решение в своем компоненте.

  • Если вы используете поток и инкапсулируете компонент в элемент экрана потока, кнопки навигации потока не будут правильно расположены в представлении.
  • Если вам нужно обработать событие touchmove для собственных нужд (например, рисование от руки на мобильном устройстве, сортируемые элементы и т. д.), вам необходимо протестировать интеграцию между описанным выше прослушивателем событий и ваша реализация.
  • Не гарантируется, что это решение будет работать «как есть» в будущем выпуске Salesforce.

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