Giter VIP home page Giter VIP logo

giraffe.htmx's Introduction

Giraffe.Htmx

Giraffe is a library that sits atop ASP.NET Core, and enables developers to create applications in a functional style (vs. the C# / object-oriented style of the base library). The Giraffe View Engine enables production of HTML views in a strongly-typed and fully-integrated-with-source fashion.

htmx is a library that embraces the idea of HTML as a programming language, where any element can fire off a request, and portions of the page can be swapped out dynamically. It does all these with a tiny, dependency-free JavaScript library.

htmx uses attributes and HTTP headers to attain its interactivity; the libraries here contain extensions to both Giraffe and Giraffe View Engine to enable strongly-typed development of htmx applications.

Installation

Giraffe.Htmx provides extensions that facilitate using htmx on the server side, primarily reading and setting headers. Giraffe.ViewEngine.Htmx provides attributes and helpers to produce views that utilize htmx. Both can be installed from NuGet via standard methods.

Server Side View Engine
Nuget Nuget

Server Side (Giraffe.Htmx)

In addition to the regular HTTP request payloads, htmx sets one or more headers along with the request. Once Giraffe.Htmx is opened, these are available as properties on HttpContext.Request.Headers. These consist of the header name, translated to a .NET name (ex. HX-Current-URL becomes HxCurrentUrl), and a strongly-typed property based on the expected value of that header. Additionally, they are all exposed as Options, as they may or may not be present for any given request.

A server may want to respond to a request that originated from htmx differently than a regular request. One way htmx can provide the same feel as a Single Page Application (SPA) is by swapping out the body content (or an element within it) instead of reloading the entire page. In this case, the developer can provide a partial layout to be used for these responses, while returning the full page for regular requests. The IsHtmx property makes this easy...

  // "partial" and "full" are handlers that return the contents;
  // "view" can be whatever your view engine needs for the body of the page
  let result view : HttpHandler =
    fun next ctx ->
      match ctx.Request.IsHtmx && not ctx.Request.IsHtmxRefresh with
      | true -> partial view
      | false -> full view

htmx also utilizes response headers to affect client-side behavior. For each of these, this library provides HttpHandlers that can be chained along with the response. As an example, if the server returns a redirect response (301, 302, 303, 307), the XMLHttpRequest handler on the client will follow the redirection before htmx can do anything with it. To redirect to a new page, you would return an OK (200) response with an HX-Redirect header set in the response.

  let theHandler : HttpHandler =
    fun next ctx ->
      // some interesting stuff
      withHxRedirect "/the-new-url" >=> Successful.OK

Of note is that the HX-Trigger headers can take either one or more events. For a single event with no parameters, use withHxTrigger; for a single event with parameters, or multiple events, use withHxTriggerMany. Both these have AfterSettle and AfterSwap versions as well.

View Engine (Giraffe.ViewEngine.Htmx)

As htmx uses attributes to extend HTML, the primary part of this library defines attributes that can be used within Giraffe views. Simply open Giraffe.ViewEngine.Htmx, and these attributes, along with support modules, will be visible.

As an example, creating a div that loads data once the HTML is rendered:

  let autoload =
    div [ _hxGet "/lazy-load-data"; _hxTrigger "load" ] [ str "Loading..." ]

(As hx-boost="true" is the usual desire for boosting, _hxBoost implies true. To disable it for an element, use _hxNoBoost instead.)

Some attributes have known values, such as hx-trigger and hx-swap; for these, there are modules with those values. For example, HxTrigger.Load could be used in the example above, to ensure that the known values are spelled correctly. hx-trigger can also take modifiers, such as an action that only responds to Ctrl+click. The HxTrigger module has a Filter submodule to assist with defining these actions.

  let shiftClick =
    p [ _hxGet = "/something"; _hxTrigger (HxTrigger.Filter.Shift HxTrigger.Click) ] [
      str "hold down Shift and click me"
      ]

If you want to load htmx from unpkg, Htmx.Script.minified or Htmx.Script.unminified can be used to load the script in your HTML trees.

Feedback / Help

The author hangs out in the #dotnet-htmx channel (and most others) of the htmx Discord server and the #web channel of the F# Software Foundation's Slack server.

Thanks

Giraffe logo htmx logo JetBrains Logo (Main)
for making ASP.NET Core functional for making HTML cool again for licensing their tools to this project

giraffe.htmx's People

Contributors

bjorn-strom avatar danieljsummers avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

Forkers

bjorn-strom

giraffe.htmx's Issues

Add HX-Retarget header

htmx 1.6.1 added an HX-Retarget response header, allowing the user to override the hx-target attribute of the initiating request. Add support for this to Giraffe.Htmx.

[Runtime Error] System.IO.FileNotFoundException: Could not load file or assembly 'FSharp.Core, Version=8.0.0.0

Hey all, love the package but can't seem to get it to work.

Context

  • Running: dotnet 7

Using in simple page:

        div [] [
            (
                if props.Page < 1
                then emptyText
                else 
                    button [
                        _hxGet $"/sentinels?page={props.Page - 1}"
                        _hxTarget $"#{sentinelTableId}"
                        _hxPushUrl "true"
                    ] [
                        str "Previous"
                    ]
            );
            (
                if not props.HasNext
                then emptyText
                else 
                    button [
                        _hxGet $"/sentinels?page={props.Page + 1}"
                        _hxTarget $"#{sentinelTableId}"
                        _hxPushUrl "true"
                    ] [
                        str "Next"
                    ]
            )
        ]

Problem

So my app builds fine but when I try to actually use one of these Giraffe.ViewEngine.Htmx imports it fails at runtime with this error:

fail: Microsoft.AspNetCore.Server.Kestrel[13]
2023-12_fsharp-htmx-giraffe-view                                                          |       Connection id "0HMVLM56KO179", Request id "0HMVLM56KO179:00000001": An unhandled exception was thrown by the application.
2023-12_fsharp-htmx-giraffe-view                                                          |       System.IO.FileNotFoundException: Could not load file or assembly 'FSharp.Core, Version=8.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'. The system cannot find the file specified.

I can reproduce this by trying to use any of these imports like this:

printfn "hamytodo: this is an _hxget %A" _hxGet

Hypothesis

I think I'm missing Fsharp.Core 8 so this may just be a me problem. But it seems odd that I can DL and use this package without any errors being thrown until runtime.

Also, I can't seem to update my Fsharp.Core to 8. I'm wondering if Fsharp 8 requires dotnet 8 so this package says it can run on dotnet 6 and 7 but actually requires 8?

idk.

Q1: Any ideas as to how this happened / ways to fix?

Q2: Any ways to prevent this from happening in the future?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.