diff --git a/src/Common/Common.fs b/src/Common/Common.fs
index 2ff982e..f288899 100644
--- a/src/Common/Common.fs
+++ b/src/Common/Common.fs
@@ -3,7 +3,7 @@
module Giraffe.Htmx.Common
/// The version of htmx embedded in the package
-let HtmxVersion = "2.0.8"
+let HtmxVersion = "4.0.0-alpha6"
/// The path for the provided htmx script
let internal htmxLocalScript = $"/_content/Giraffe.Htmx.Common/htmx.min.js?ver={HtmxVersion}"
@@ -25,8 +25,8 @@ let internal toLowerBool (boolValue: bool) =
/// Valid values for the hx-swap attribute / HX-Reswap header
-/// May be combined with swap / settle / scroll / show config)
-/// Documentation
+/// May be combined with swap / scroll / show config)
+/// Documentation
[]
module HxSwap =
@@ -38,22 +38,60 @@ module HxSwap =
[]
let OuterHtml = "outerHTML"
+ /// Morph the inner HTML of the target to the new content
+ []
+ let InnerMorph = "innerMorph"
+
+ /// Morph the outer HTML of the target to the new content
+ []
+ let OuterMorph = "innerMorph"
+
+ /// Replace the text content of the target without parsing the response as HTML
+ []
+ let TextContent = "textContent"
+
/// Insert the response before the target element
[]
- let BeforeBegin = "beforebegin"
+ let Before = "before"
+
+ /// Insert the response before the target element (pre-v4 name)
+ []
+ let BeforeBegin = Before
/// Insert the response before the first child of the target element
[]
- let AfterBegin = "afterbegin"
+ let Prepend = "prepend"
+
+ /// Insert the response before the first child of the target element (pre-v4 name)
+ []
+ let AfterBegin = Prepend
/// Insert the response after the last child of the target element
[]
- let BeforeEnd = "beforeend"
+ let Append = "append"
+
+ /// Insert the response after the last child of the target element (pre-v4 name)
+ []
+ let BeforeEnd = Append
/// Insert the response after the target element
[]
- let AfterEnd = "afterend"
+ let After = "after"
+
+ /// Insert the response after the target element (pre-v4 name)
+ []
+ let AfterEnd = After
- /// Does not append content from response (out of band items will still be processed).
+ /// Delete the target element regardless of response
+ []
+ let Delete = "delete"
+
+ /// Does not append content from response (out of band items will still be processed)
[]
let None = "none"
+
+ /// Update existing elements by id and add new ones
+ /// This requires the upsert extension
+ /// Extension
+ []
+ let Upsert = "upsert"
diff --git a/src/Htmx/Htmx.fs b/src/Htmx/Htmx.fs
index c1b100f..99b9d6d 100644
--- a/src/Htmx/Htmx.fs
+++ b/src/Htmx/Htmx.fs
@@ -24,6 +24,7 @@ type IHeaderDictionary with
with get () = hdr this "HX-History-Restore-Request" |> Option.map bool.Parse
/// The user response to an hx-prompt
+ []
member this.HxPrompt
with get () = hdr this "HX-Prompt"
@@ -31,15 +32,29 @@ type IHeaderDictionary with
member this.HxRequest
with get () = hdr this "HX-Request" |> Option.map bool.Parse
+ /// The tag name (fst) and id attribute (snd) of the element triggering this request
+ member this.HxSource
+ with get () =
+ match hdr this "HX-Source" with
+ | Some src ->
+ let parts = src.Split "#"
+ if parts.Length = 1 then
+ Some (parts[0], None)
+ else
+ Some (parts[0], if parts[1] <> "" then Some parts[1] else None)
+ | None -> None
+
/// The id attribute of the target element if it exists
member this.HxTarget
with get () = hdr this "HX-Target"
/// The id attribute of the triggered element if it exists
+ []
member this.HxTrigger
with get () = hdr this "HX-Trigger"
/// The name attribute of the triggered element if it exists
+ []
member this.HxTriggerName
with get () = hdr this "HX-Trigger-Name"
diff --git a/src/Tests/Common.fs b/src/Tests/Common.fs
index 959596c..1d3972b 100644
--- a/src/Tests/Common.fs
+++ b/src/Tests/Common.fs
@@ -6,7 +6,7 @@ open Giraffe.Htmx
/// Test to ensure the version was updated
let version =
test "HtmxVersion is correct" {
- Expect.equal HtmxVersion "2.0.8" "htmx version incorrect"
+ Expect.equal HtmxVersion "4.0.0-alpha6" "htmx version incorrect"
}
/// Tests for the HxSwap module
@@ -18,21 +18,48 @@ let swap =
test "OuterHtml is correct" {
Expect.equal HxSwap.OuterHtml "outerHTML" "Outer HTML swap value incorrect"
}
- test "BeforeBegin is correct" {
- Expect.equal HxSwap.BeforeBegin "beforebegin" "Before Begin swap value incorrect"
+ test "InnerMorph is correct" {
+ Expect.equal HxSwap.InnerMorph "innerMorph" "Inner Morph swap value incorrect"
}
- test "BeforeEnd is correct" {
- Expect.equal HxSwap.BeforeEnd "beforeend" "Before End swap value incorrect"
+ test "OuterMorph is correct" {
+ Expect.equal HxSwap.OuterMorph "innerMorph" "Outer Morph swap value incorrect"
+ }
+ test "TextContent is correct" {
+ Expect.equal HxSwap.TextContent "textContent" "Text Content swap value incorrect"
+ }
+ test "Before is correct" {
+ Expect.equal HxSwap.Before "before" "Before swap value incorrect"
+ }
+ test "BeforeBegin is correct" {
+ Expect.equal HxSwap.BeforeBegin HxSwap.Before "Before Begin swap value incorrect"
+ }
+ test "Prepend is correct" {
+ Expect.equal HxSwap.Prepend "prepend" "Prepend swap value incorrect"
}
test "AfterBegin is correct" {
- Expect.equal HxSwap.AfterBegin "afterbegin" "After Begin swap value incorrect"
+ Expect.equal HxSwap.AfterBegin HxSwap.Prepend "Prepend swap value incorrect"
+ }
+ test "Append is correct" {
+ Expect.equal HxSwap.Append "append" "Append swap value incorrect"
+ }
+ test "BeforeEnd is correct" {
+ Expect.equal HxSwap.BeforeEnd HxSwap.Append "Before End swap value incorrect"
+ }
+ test "After is correct" {
+ Expect.equal HxSwap.After "after" "After swap value incorrect"
}
test "AfterEnd is correct" {
- Expect.equal HxSwap.AfterEnd "afterend" "After End swap value incorrect"
+ Expect.equal HxSwap.AfterEnd HxSwap.After "After End swap value incorrect"
+ }
+ test "Delete is correct" {
+ Expect.equal HxSwap.Delete "delete" "Delete swap value incorrect"
}
test "None is correct" {
Expect.equal HxSwap.None "none" "None swap value incorrect"
}
+ test "Upsert is correct" {
+ Expect.equal HxSwap.Upsert "upsert" "Upsert swap value incorrect"
+ }
]
/// All tests for this module
diff --git a/src/ViewEngine.Htmx/Htmx.fs b/src/ViewEngine.Htmx/Htmx.fs
index c73a81e..8ea89bd 100644
--- a/src/ViewEngine.Htmx/Htmx.fs
+++ b/src/ViewEngine.Htmx/Htmx.fs
@@ -1,6 +1,8 @@
/// Types and functions supporting htmx attributes in Giraffe View Engine
module Giraffe.ViewEngine.Htmx
+open System.Net.Http
+
/// Valid values for the hx-encoding attribute
[]
module HxEncoding =
@@ -21,17 +23,20 @@ type HxEvent =
/// Send this event to an element to abort a request
| Abort
+ /// Triggered after a request has initialized
+ | AfterInit
+
/// Triggered after an AJAX request has completed processing a successful response
- | AfterOnLoad
+ | [] AfterOnLoad
/// Triggered after htmx has initialized a node
- | AfterProcessNode
+ | [] AfterProcessNode
/// Triggered after an AJAX request has completed
| AfterRequest
/// Triggered after the DOM has settled
- | AfterSettle
+ | [] AfterSettle
/// Triggered after new content has been swapped in
| AfterSwap
@@ -39,20 +44,32 @@ type HxEvent =
/// Triggered before htmx disables an element or removes it from the DOM
| BeforeCleanupElement
+ /// Triggered before content is saved to the history cache
+ | [] BeforeHistorySave
+
+ /// Triggered before content is saved to the history cache
+ | BeforeHistoryUpdate
+
+ /// Triggered before htmx initializes a node
+ | BeforeInit
+
/// Triggered before any response processing occurs
- | BeforeOnLoad
+ | [] BeforeOnLoad
/// Triggered before htmx initializes a node
| BeforeProcessNode
- /// Triggered before an AJAX request is made
+ /// Triggered before an HTTP request is made
| BeforeRequest
+ /// Triggered just before an ajax request is sent
+ | [] BeforeSend
+
/// Triggered before a swap is done, allows you to configure the swap
| BeforeSwap
- /// Triggered just before an ajax request is sent
- | BeforeSend
+ /// Triggered before a CSS view transition starts
+ | BeforeTransition
/// Triggered before the request, allows you to customize parameters, headers
| ConfigRequest
@@ -77,9 +94,6 @@ type HxEvent =
/// Triggered when htmx handles a history restoration action
| HistoryRestore
- /// Triggered before content is saved to the history cache
- | BeforeHistorySave
-
/// Triggered when new content is added to the DOM
| Load
@@ -151,25 +165,29 @@ type HxEvent =
/// The htmx event name (fst) and kebab-case name (snd, for use with hx-on)
static member private Values = Map [
Abort, ("abort", "abort")
- AfterOnLoad, ("afterOnLoad", "after-on-load")
- AfterProcessNode, ("afterProcessNode", "after-process-node")
- AfterRequest, ("afterRequest", "after-request")
- AfterSettle, ("afterSettle", "after-settle")
- AfterSwap, ("afterSwap", "after-swap")
- BeforeCleanupElement, ("beforeCleanupElement", "before-cleanup-element")
- BeforeOnLoad, ("beforeOnLoad", "before-on-load")
- BeforeProcessNode, ("beforeProcessNode", "before-process-node")
- BeforeRequest, ("beforeRequest", "before-request")
- BeforeSwap, ("beforeSwap", "before-swap")
- BeforeSend, ("beforeSend", "before-send")
- ConfigRequest, ("configRequest", "config-request")
+ AfterInit, ("afterInit", "after:init")
+ AfterOnLoad, ("afterOnLoad", "after:init")
+ AfterProcessNode, ("afterProcessNode", "after:init")
+ AfterRequest, ("afterRequest", "after:request")
+ AfterSettle, ("afterSettle", "after:swap")
+ AfterSwap, ("afterSwap", "after:swap")
+ BeforeCleanupElement, ("beforeCleanupElement", "before:cleanup:element")
+ BeforeHistorySave, ("beforeHistorySave", "before:history:update")
+ BeforeHistoryUpdate, ("beforeHistoryUpdate", "before:history:update")
+ BeforeInit, ("beforeInit", "before:init")
+ BeforeOnLoad, ("beforeOnLoad", "before:init")
+ BeforeProcessNode, ("beforeProcessNode", "before:process")
+ BeforeRequest, ("beforeRequest", "before:request")
+ BeforeSend, ("beforeSend", "before:send")
+ BeforeSwap, ("beforeSwap", "before:swap")
+ BeforeTransition, ("beforeTransition", "before:viewTransition")
+ ConfigRequest, ("configRequest", "config:request")
Confirm, ("confirm", "confirm")
HistoryCacheError, ("historyCacheError", "history-cache-error")
HistoryCacheMiss, ("historyCacheMiss", "history-cache-miss")
HistoryCacheMissError, ("historyCacheMissError", "history-cache-miss-error")
HistoryCacheMissLoad, ("historyCacheMissLoad", "history-cache-miss-load")
HistoryRestore, ("historyRestore", "history-restore")
- BeforeHistorySave, ("beforeHistorySave", "before-history-save")
Load, ("load", "load")
NoSseSourceError, ("noSSESourceError", "no-sse-source-error")
OnLoadError, ("onLoadError", "on-load-error")
@@ -493,11 +511,23 @@ open Giraffe.Htmx
[]
module HtmxAttrs =
+ /// The URL which will receive the request (use with _hxMethod)
+ /// The URL for the attribute
+ /// Documentation
+ let _hxAction url = attr "hx-action" url
+
/// Progressively enhances anchors and forms to use AJAX requests
/// Use _hxNoBoost to set to false
/// Documentation
let _hxBoost = attr "hx-boost" "true"
+ /// Configure request behavior
+ /// The configuration parameters to use for the request
+ /// A configured hx-config attribute
+ /// Documentation
+ let _hxConfig config =
+ attr "hx-config" (toJson config)
+
/// Shows a confirm() dialog before issuing a request
/// The prompt to present to the user when seeking their confirmation
/// A configured hx-confirm attribute
@@ -512,14 +542,23 @@ module HtmxAttrs =
let _hxDelete url =
attr "hx-delete" url
- /// Disables htmx processing for the given node and any children nodes
- /// Documentation
- let _hxDisable = flag "hx-disable"
+ /// Specifies elements that should be disabled when an htmx request is in flight
+ /// The element to disable when an htmx request is in flight
+ /// A configured hx-disable attribute
+ /// This behavior changed in v4
+ /// - For the v2 behavior of hx-disable (which will manifest as compile errors), change instances to
+ /// _hxIgnore
+ /// - For v4 behavior, changing _hxDisabledElt to _hxDisable should be sufficient
+ ///
+ /// Documentation
+ let _hxDisable elt =
+ attr "hx-disable" elt
/// Specifies elements that should be disabled when an htmx request is in flight
/// The element to disable when an htmx request is in flight
/// A configured hx-disabled-elt attribute
/// Documentation
+ []
let _hxDisabledElt elt =
attr "hx-disabled-elt" elt
@@ -527,6 +566,7 @@ module HtmxAttrs =
/// The htmx attributes to disinherit (should start with "hx-")
/// A configured hx-disinherit attribute
/// Documentation
+ []
let _hxDisinherit hxAttrs =
attr "hx-disinherit" hxAttrs
@@ -542,6 +582,7 @@ module HtmxAttrs =
/// A list of extensions to apply to this element
/// A configured hx-ext attribute
/// Documentation
+ []
let _hxExt exts =
attr "hx-ext" exts
@@ -565,14 +606,21 @@ module HtmxAttrs =
/// Whether the page should be stored in the history cache
/// A configured hx-history attribute
/// Documentation
+ []
let _hxHistory shouldStore =
attr "hx-history" (toLowerBool shouldStore)
/// The element to snapshot and restore during history navigation
/// Documentation
+ []
let _hxHistoryElt =
flag "hx-history-elt"
+ /// Disables htmx processing for the given node and any children nodes
+ /// Documentation
+ let _hxIgnore =
+ flag "hx-ignore"
+
/// Includes additional data in AJAX requests
/// The specification of what should be included in the request
/// A configured hx-include attribute
@@ -587,6 +635,12 @@ module HtmxAttrs =
let _hxIndicator selector =
attr "hx-indicator" selector
+ /// The HTTP method to use for the request(use with _hxAction)
+ /// The method to use
+ /// Documentation
+ let _hxMethod (method: HttpMethod) =
+ attr "hx-method" (method.Method.ToLowerInvariant())
+
/// Overrides a previous hx-boost (hx-boost="false")
/// Documentation
let _hxNoBoost =
@@ -614,6 +668,7 @@ module HtmxAttrs =
/// A configured hx-params attribute
///
/// Documentation
+ []
let _hxParams toInclude =
attr "hx-params" toInclude
@@ -641,6 +696,7 @@ module HtmxAttrs =
/// A configured hx-prompt attribute
/// The value provided will be in the HX-Prompt request header
/// Documentation
+ []
let _hxPrompt text =
attr "hx-prompt" text
@@ -682,6 +738,7 @@ module HtmxAttrs =
/// A configured hx-request attribute
///
/// Documentation
+ []
let _hxRequest spec =
attr "hx-request" spec
@@ -785,6 +842,35 @@ module HtmxAttrs =
attr "sse-swap" messages
+/// Modifiers for htmx attributes
+[]
+module HxModifiers =
+
+ /// Append this value to any inherited value of the attribute
+ /// The attribute to which :append should be applied
+ /// The given attribute with :append applied
+ let hxAppend attrib =
+ match attrib with
+ | KeyValue (name, value) -> attr $"{name}:append" value
+ | Boolean name -> flag $"{name}:append"
+
+ /// Explicity inherit the value for this attribute
+ /// The attribute whose value should be inherited
+ /// The given attribute with :inherited applied
+ let hxInherit attrib =
+ match attrib with
+ | KeyValue (name, value) -> attr $"{name}:inherited" value
+ | Boolean name -> flag $"{name}:inherited"
+
+
+/// htmx-specific HTML tags
+[]
+module HxTags =
+
+ /// An hx-partial tag
+ let hxPartial = tag "hx-partial"
+
+
/// Script tags to pull htmx into a web page
module Script =