seaworn / symfony-htmx-bundle

Symfony 的 Htmx 集成

安装次数: 14

依赖项: 0

建议者: 0

安全: 0

星标: 3

关注者: 2

分支: 1

开放问题: 0

类型:symfony-bundle

dev-main 2024-01-10 22:28 UTC

This package is auto-updated.

Last update: 2024-09-10 23:50:26 UTC


README

Symfony 的 Htmx 集成

  • Symfony >=6.0
  • PHP >=8.0

安装

$ composer require seaworn/symfony-htmx-bundle

设置

将以下片段添加到前端控制器中。这将允许 Symfony 使用自定义的请求类

/* public/index.php */

\Symfony\Component\HttpFoundation\Request::setFactory(function (...$args) {
    return new \Seaworn\HtmxBundle\Request\HtmxRequest(...$args);
});

用法

Seaworn\HtmxBundle\Controller\AbstractController 扩展你的控制器,或者使用 Seaworn\HtmxBundle\Controller\HtmxControllerTrait 特性

// ...
use Seaworn\HtmxBundle\Request\HtmxRequest;
use Seaworn\HtmxBundle\Response\HtmxResponse;

class HelloController extends \Seaworn\HtmxBundle\Controller\AbstractController{}

// or

class HelloController extends \Symfony\Bundle\FrameworkBundle\Controller\AbstractController
{
    use \Seaworn\HtmxBundle\Controller\HtmxControllerTrait;
}

请求头

public function index(HtmxRequest $request): HtmxResponse
{
    // whether the request is made via htmx
    $request->isHtmxRequest();

    // whether the request is via an element using hx-boost attribute
    $request->isBoosted();
    
    // the current browser url
    $request->getCurrentUrl();
    
    // whether request is for history restoration after a miss in the local history cache
    $request->isHistoryRestoreRequest();
    
    // the user response to an hx-prompt
    $request->getPromptResponse();
    
    // the id of the target element if it exists
    $request->getTargetId();

    // the id of the triggered element if it exists
    $request->getTriggerId();
    
    // the name of the triggered element if it exists
    $request->getTriggerName();
    
    // ...
}

响应头

public function index(HtmxRequest $request): HtmxResponse
{
    // ...

    return $this->htmxRender('index.html.twig') // or new HtmxResponse()
        // Optional headers
        ->setLocation(
            "/location", 
            [
              'source' => '',
              'event' => '',
              'handler' => '',
              'target' => '',
              'swap' => '',
              'select' => ''
              'values' => [],
              'headers' => [],
            ]
        )) // set HX-Location header
        ->setPushUrl('/push') // set HX-Push-Url header
        ->setReplaceUrl('/replace') // set HX-Replace-Url header
        ->setReswap('outerHTML') // set HX-Reswap header
        ->setRetarget('#target') // set HX-Retarget header
        ->setReselect('#select') // set HX-Reselect header
        ->setTriggers('event') // set HX-Trigger header (simple)
        ->setAfterSwapTriggers('event1,event2') // set HX-Trigger-After-Swap header (multiple)
        ->setAfterSettleTriggers(['event' => ['key' => 'value']]); // set HX-Trigger-After-Settle header (with detail)
}

渲染模板块

<!-- index.html.twig -->

{% extends 'base.html.twig' %}

{% block block1 %}
    <div id="block1"> 
        Sample content...
    </div>
{% endblock %}
public function index(HtmxRequest $request): HtmxResponse
{
    return $this->htmxRenderBlock('index.html.twig', 'block1');
}

重定向

public function index(HtmxRequest $request): HtmxResponse
{
    return $this->htmxRedirect('https://htmx.npmjs.net.cn/');
}

刷新

public function index(HtmxRequest $request): HtmxResponse
{
    return $this->htmxRefresh();
}

停止 轮询

<!-- index.html.twig -->

{% extends 'base.html.twig' %}

{% block content %}
    <div hx-get="/poll" hx-vals="js:{pollingIndex}" hx-trigger="every 2s"></div>
    <script type="text/javascript">
        var pollingIndex = 0;
        document.body.addEventListener("polling", function(e) {
            pollingIndex++;
            console.log("Polling Index:", pollingIndex);
        });
    </script>
{% endblock %}
public function poll(HtmxRequest $request): HtmxResponse
{ 
    $index = $request->get('pollingIndex', 0);
    if ((int)$index >= 10) {
        return new HtmxStopPollingResponse();
    }
    return (new HtmxResponse())->setTriggers('polling');
}