Stimulus Outlet API
- stimulus
เราเคยพูดถึงเรื่องการสื่อสารกันระหว่าง controller ผ่านการใช้ Custom Event 🔗 เมื่อ Stimulus 3.2 ได้ปล่อย Outlet API ออกมาเพื่อใช้ในการสื่อสารระหว่าง controller ผ่าน outlet ซึ่งเป็นอีกทางเลือกหนึ่ง
นิยาม outlet attribute
เพื่อใช้สื่อสารข้ามระหว่าง controller ดังนั้นเราต้องกำหนด outlet ที่จะคุยด้วย และอ้างอิงถึงคอมโพเนนต์ผ่าน CSS Selector
// Syntax
data-[identifier]-[outlet]-outlet="[selector]"
// Example
<ul id="sidebar" data-controller="sidebar" data-sidebar-content-outlet="#area">
ตัวอย่างข้างต้น จะเห็นว่า sidebar controller
ต้องการสื่อสารกับ content controller (outlet)
ผ่าน #area (id="area")
สำหรับโค้ดที่สมบูรณ์จะอยู่ด้านล่าง โดยเราจะทำตัวอย่างให้ใกล้เคียงกับตัวอย่างของบทความที่แล้ว
<div class="flex flex-row">
<div class="flex flex-row gap-4 w-full">
<ul id="sidebar" data-controller="sidebar" data-sidebar-content-outlet="#area">
<li>
<button class="w-48 border rounded-lg bg-gray-100 cursor-pointer mb-2 p-4 text-left" data-action="click->sidebar#load" data-url="/about">About</button>
</li>
<li>
<button class="w-48 border rounded-lg bg-gray-100 cursor-pointer mb-2 p-4 text-left" data-action="click->sidebar#load" data-url="/contact">Contact</button>
</li>
</ul>
<div id="area" class="w-full border rounded-lg bg-gray-100 p-4" data-controller="content">
</div>
</div>
</div>
// sidebar_controller.js
import { Controller } from "@hotwired/stimulus"
import { get } from "@rails/request.js";
export default class extends Controller {
static outlets = [ "content" ]
async connect() {
const element = this.element.querySelector("[data-url]")
if (element) {
await this.loadContent(element)
}
}
async load(event) {
await this.loadContent(event.target)
}
async loadContent(element) {
const url = element.getAttribute("data-url")
const response = await get(url)
if (response.ok) {
this.contentOutletElement.innerHTML = await response.html
}
}
}
ตัวอย่าง