Controllers+Views+Routes: Add ScriptAfterLoad functionality
This commit is contained in:
+7
-1
@@ -1,11 +1,17 @@
|
|||||||
|
window.web = {};
|
||||||
|
|
||||||
|
// -----------------------------------------
|
||||||
|
|
||||||
// Activate Bootstrap tooltips
|
// Activate Bootstrap tooltips
|
||||||
|
web.tooltips = function() {
|
||||||
const tooltipTriggerList = document.querySelectorAll('[data-bs-toggle="tooltip"]')
|
const tooltipTriggerList = document.querySelectorAll('[data-bs-toggle="tooltip"]')
|
||||||
const tooltipList = [...tooltipTriggerList].map(element => new bootstrap.Tooltip(element))
|
const tooltipList = [...tooltipTriggerList].map(element => new bootstrap.Tooltip(element))
|
||||||
|
}
|
||||||
|
|
||||||
// -----------------------------------------
|
// -----------------------------------------
|
||||||
// HTMX events
|
// HTMX events
|
||||||
|
|
||||||
function runOnceAfterSettle(func) {
|
web.afterLoad = function(func) {
|
||||||
// https://htmx.org/docs/#request-operations
|
// https://htmx.org/docs/#request-operations
|
||||||
document.addEventListener("htmx:afterSettle", function handler(event) {
|
document.addEventListener("htmx:afterSettle", function handler(event) {
|
||||||
func();
|
func();
|
||||||
|
|||||||
@@ -0,0 +1,30 @@
|
|||||||
|
import Elementary
|
||||||
|
import ElementaryHTMX
|
||||||
|
import ElementaryHTMXSSE
|
||||||
|
import ElementaryHTMXWS
|
||||||
|
import Fluent
|
||||||
|
import Vapor
|
||||||
|
import VaporElementary
|
||||||
|
|
||||||
|
struct TestController: RouteCollection {
|
||||||
|
|
||||||
|
func boot(routes: RoutesBuilder) throws {
|
||||||
|
routes.group("test") { test in
|
||||||
|
test.get("toast", use: toast)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Sendable
|
||||||
|
func toast(req: Request) async throws -> HTMLResponse {
|
||||||
|
|
||||||
|
let state = try getState(request: req)
|
||||||
|
state.toast = ToastState(message: "Wow!",
|
||||||
|
title: "This is my title",
|
||||||
|
level: ToastState.Level.success)
|
||||||
|
|
||||||
|
throw Abort(.badRequest, headers: ["HX-Trigger": "toast"])
|
||||||
|
|
||||||
|
// return HTMLResponse { }
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -27,6 +27,8 @@ struct TodoController: RouteCollection {
|
|||||||
MainLayout(title: "Todos") {
|
MainLayout(title: "Todos") {
|
||||||
TodosTableComponent(name: "todos", todos: todos)
|
TodosTableComponent(name: "todos", todos: todos)
|
||||||
TodosFormComponent(name: "todos-form", target: "todos")
|
TodosFormComponent(name: "todos-form", target: "todos")
|
||||||
|
|
||||||
|
button(.class("btn btn-primary"), .type(.button), .hx.get("/test/toast")) { "Toast" }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-4
@@ -9,7 +9,7 @@ import ElementaryHTMX
|
|||||||
//
|
//
|
||||||
// The header "HX-Trigger" will make the part refresh and show the toast message
|
// The header "HX-Trigger" will make the part refresh and show the toast message
|
||||||
|
|
||||||
struct ToastView: HTML {
|
struct ToastComponent: HTML {
|
||||||
|
|
||||||
var state: ToastState = ToastState()
|
var state: ToastState = ToastState()
|
||||||
|
|
||||||
@@ -33,9 +33,8 @@ struct ToastView: HTML {
|
|||||||
div(.class("toast-body")) { state.message }
|
div(.class("toast-body")) { state.message }
|
||||||
}
|
}
|
||||||
if !state.message.isEmpty {
|
if !state.message.isEmpty {
|
||||||
script {
|
ScriptAfterLoad(initial: false) {
|
||||||
"""
|
"""
|
||||||
runOnceAfterSettle(function () {
|
|
||||||
const element = document.getElementById("toast");
|
const element = document.getElementById("toast");
|
||||||
const toast = new bootstrap.Toast(element, { autohide: true, delay: 5000 });
|
const toast = new bootstrap.Toast(element, { autohide: true, delay: 5000 });
|
||||||
toast.show();
|
toast.show();
|
||||||
@@ -43,7 +42,6 @@ struct ToastView: HTML {
|
|||||||
element.addEventListener("hidden.bs.toast", function () {
|
element.addEventListener("hidden.bs.toast", function () {
|
||||||
element.remove();
|
element.remove();
|
||||||
});
|
});
|
||||||
});
|
|
||||||
"""
|
"""
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -47,6 +47,8 @@ struct TodosTableComponent: HTML {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ScriptAfterLoad(initial: !refresh) { "web.tooltips();" };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -59,7 +59,7 @@ struct MainLayout<Body: HTML>: HTMLDocument {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Placeholder for all toast messages
|
// Placeholder for all toast messages
|
||||||
ToastView()
|
ToastComponent()
|
||||||
}
|
}
|
||||||
|
|
||||||
// ---------------------------------
|
// ---------------------------------
|
||||||
|
|||||||
@@ -0,0 +1,35 @@
|
|||||||
|
import Elementary
|
||||||
|
|
||||||
|
struct ScriptAfterLoad: HTML {
|
||||||
|
|
||||||
|
var initial: Bool = false
|
||||||
|
var js: String = ""
|
||||||
|
|
||||||
|
init(initial: Bool = false, js: () -> String) {
|
||||||
|
self.initial = initial
|
||||||
|
self.js = js()
|
||||||
|
}
|
||||||
|
|
||||||
|
// -------------------------------------
|
||||||
|
|
||||||
|
var content: some HTML {
|
||||||
|
if initial {
|
||||||
|
script {
|
||||||
|
"""
|
||||||
|
document.addEventListener("DOMContentLoaded", function() {
|
||||||
|
\(js)
|
||||||
|
});
|
||||||
|
"""
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
script {
|
||||||
|
"""
|
||||||
|
web.afterLoad(function () {
|
||||||
|
\(js)
|
||||||
|
});
|
||||||
|
"""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -21,6 +21,7 @@ func routes(_ app: Application) throws {
|
|||||||
app.get("toast", use: toast)
|
app.get("toast", use: toast)
|
||||||
|
|
||||||
try app.register(collection: TodoController())
|
try app.register(collection: TodoController())
|
||||||
|
try app.register(collection: TestController())
|
||||||
|
|
||||||
try app.group("api") { api in
|
try app.group("api") { api in
|
||||||
try api.register(collection: TodoAPIController())
|
try api.register(collection: TodoAPIController())
|
||||||
@@ -32,7 +33,7 @@ func toast(req: Request) throws -> HTMLResponse {
|
|||||||
let state = try getState(request: req)
|
let state = try getState(request: req)
|
||||||
|
|
||||||
return HTMLResponse {
|
return HTMLResponse {
|
||||||
ToastView(state: state.toast)
|
ToastComponent(state: state.toast)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user