Пользовательские действия потока Turbo

Turbo Hotwire — это здорово, мне очень нравится простота турбо-фреймов. Но после использования CableReady турбо-потоки кажутся немного ограниченными. Я был удивлен, когда не смог найти ни одного драгоценного камня/пакета, который бы улучшал турбо-потоки для создания пользовательских турбо-действий.

Отказ от ответственности: Этот пост не будет иметь большого смысла для вас, если вы не знакомы с турбо-потоками и StimulusJS.

Допустим, если вы хотите перенаправить на новую страницу после выполнения какой-то работы, или сбросить форму, нет способа сделать это с помощью турбо-потокового действия. С помощью CableReady вы можете сделать следующее

Поэтому мне стало интересно, как можно создать пользовательские действия турбопотока. Судя по тому, как DHH (оригинальный создатель Rails) обсуждал турбо-потоки, маловероятно, что turbo будет поддерживать больше действий, есть
ожидается PR, но мало что изменилось.

Так что же мы можем сделать сегодня?

Стимулирующие контроллеры на помощь

Мы можем имитировать паттерн, который используют турбо-потоки, с помощью StimulusJS. В StimulusJS есть метод жизненного цикла под названием connect, который выполняется, когда в DOM добавляется новый элемент со стимул-контроллером.

Для примера с перенаправлением мы можем написать что-то вроде этого:


import { Controller } from "@hotwired/stimulus"

export default class extends Controller {
      // take a value as an argument where to redirect
    static values = { url: String } 
    connect() {
        // perform wanted behavior
        Turbo.visit(this.urlValue)
        // clean up after action is executed
      this.element.remove()
    }
}
Войти в полноэкранный режим Выйти из полноэкранного режима

Таким образом, следующий html, добавленный в любое место тела, будет выполнять перенаправление:

<template data-controller="redirect" data-redirect-url-value="<%= your_redirect_url %>"></template>
Войти в полноэкранный режим Выйти из полноэкранного режима

Таким образом, с помощью турбо-потока мы можем прикрепить это к телу:

<%= turbo_stream.append_all "body" do %>
    <template data-controller="redirect" data-redirect-url-value="<%= your_redirect_url %>"></template>
<% end %>
Войти в полноэкранный режим Выйти из полноэкранного режима

И браузер будет перенаправлен, учитывая этот ответ турбо-потока. BTW: Мы используем append_all, чтобы мы могли добавлять в тело, не полагаясь на наличие элемента с определенным id.

Лучший опыт разработчика

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

<%= turbo_stream_action :redirect, url: "http://www.rstuder.ch" %>
Войти в полноэкранный режим Выйти из полноэкранного режима

Таким образом, мы можем написать помощник, создающий тег turbo stream, который будет добавляться к телу и преобразовывать хэш значений в значения для контроллера стимулов:

module TurboStreamHelper
  def turbo_stream_action(action, **values)
    controller_name = action.to_s.dasherize

    data_attrs = {
      "data-controller" => controller_name
    }

    data_attrs = values.each_with_object(data_attrs) do |(key, value), attrs|
      attrs["data-#{controller_name}-#{key.to_s.dasherize}-value"] = value
    end

    turbo_stream.append_all "body" do
      content_tag(:template, nil, data_attrs.merge)
    end
  end
end
Войти в полноэкранный режим Выход из полноэкранного режима

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

Заключение

Турбо-потоки с контроллерами стимулов дают нам достаточно возможностей для достижения пользовательских действий. Без дополнительных зависимостей. Если вы все равно используете CableReady, то взгляните на
этот пакет от замечательного Марко Рота, который позволяет вам использовать операции cable ready с турбо-потоками.

ps: Этот пост был первоначально опубликован на rstuder.ch

Оцените статью
Procodings.ru
Добавить комментарий