Controllers+Views+Routes: Add ScriptAfterLoad functionality
This commit is contained in:
+9
-3
@@ -1,11 +1,17 @@
|
||||
window.web = {};
|
||||
|
||||
// -----------------------------------------
|
||||
|
||||
// Activate Bootstrap tooltips
|
||||
const tooltipTriggerList = document.querySelectorAll('[data-bs-toggle="tooltip"]')
|
||||
const tooltipList = [...tooltipTriggerList].map(element => new bootstrap.Tooltip(element))
|
||||
web.tooltips = function() {
|
||||
const tooltipTriggerList = document.querySelectorAll('[data-bs-toggle="tooltip"]')
|
||||
const tooltipList = [...tooltipTriggerList].map(element => new bootstrap.Tooltip(element))
|
||||
}
|
||||
|
||||
// -----------------------------------------
|
||||
// HTMX events
|
||||
|
||||
function runOnceAfterSettle(func) {
|
||||
web.afterLoad = function(func) {
|
||||
// https://htmx.org/docs/#request-operations
|
||||
document.addEventListener("htmx:afterSettle", function handler(event) {
|
||||
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") {
|
||||
TodosTableComponent(name: "todos", todos: 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
|
||||
|
||||
struct ToastView: HTML {
|
||||
struct ToastComponent: HTML {
|
||||
|
||||
var state: ToastState = ToastState()
|
||||
|
||||
@@ -33,9 +33,8 @@ struct ToastView: HTML {
|
||||
div(.class("toast-body")) { state.message }
|
||||
}
|
||||
if !state.message.isEmpty {
|
||||
script {
|
||||
ScriptAfterLoad(initial: false) {
|
||||
"""
|
||||
runOnceAfterSettle(function () {
|
||||
const element = document.getElementById("toast");
|
||||
const toast = new bootstrap.Toast(element, { autohide: true, delay: 5000 });
|
||||
toast.show();
|
||||
@@ -43,7 +42,6 @@ struct ToastView: HTML {
|
||||
element.addEventListener("hidden.bs.toast", function () {
|
||||
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
|
||||
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)
|
||||
|
||||
try app.register(collection: TodoController())
|
||||
try app.register(collection: TestController())
|
||||
|
||||
try app.group("api") { api in
|
||||
try api.register(collection: TodoAPIController())
|
||||
@@ -32,7 +33,7 @@ func toast(req: Request) throws -> HTMLResponse {
|
||||
let state = try getState(request: req)
|
||||
|
||||
return HTMLResponse {
|
||||
ToastView(state: state.toast)
|
||||
ToastComponent(state: state.toast)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user