bigskysoftware / htmx

</> htmx - high power tools for HTML
https://htmx.org
Other
37.49k stars 1.27k forks source link

how to handle 404, 500 from api and display custom error messages? #494

Closed darcwader closed 3 years ago

darcwader commented 3 years ago
  <button hx-post="/clicked" hx-swap="outerHTML">
    Click Me
  </button>

in the above snipped. i would like to handle by displaying an error message for error cases.

i've tried sample to just show templates, i understand sending template for error for validation is the approach, but i am trying to handle cases when server is not accessible. or if url has changed.

i know i have to use https://htmx.org/events/#htmx:responseError . how do i use it?

paxperscientiam commented 3 years ago

Not sure about that property, but thing i do for situations where I do have control is to send the right partial and desired HTTP code for a given scenario.

try {
  if (new Service()-> response->sucess) {
    echo partialLoader("partial", $data);
  } 
} catch (Exception $e) {
   http_response_code(500);
   echo partialLoader("partial_500", []);
}

The above is PHP/pseudo. I hope it's clear enough!

EDIT: Here's the actual answer you're looking for:

             htmx.on("htmx:responseError", function () {
                 console.error("omfg");
             })
1cg commented 3 years ago

thank you @paxperscientiam ! That's the right thing!

jeanmonet commented 3 years ago

Here's a basic approach I went for (maybe can be improved?):

<div id="errormessages">
</div>

<script>
   htmx.on("htmx:responseError", function(evt) {
     var errdiv = document.getElementById("errormessages");
     errdiv.innerHTML = `
        <div id="errormessagealert" class="container mt-3 mb-3 alert alert-danger" role="alert">
            <h4>Request Error: ` + evt.detail.xhr.status + `
                <span style="float:right;"><a onclick="errormessagealert_off()">Close [X]</a></span>
            </h4>
            <code>` + evt.detail.xhr.responseText + `</code>
        </div>`;
     errormessagealert_on();
   });

  function errormessagealert_on() {
    document.getElementById("errormessagealert").style.display = "block";
  }

  function errormessagealert_off() {
    document.getElementById("errormessagealert").style.display = "none";
  }
</script>

<style>
  #errormessagealert {
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%,-50%);
    -ms-transform: translate(-50%,-50%);
    display: none; /* Hidden by default */
    background-color: rgba(0,0,0,0.8); /* Black background with opacity */
    z-index: 2; /* Specify a stack order in case you're using a different order for other elements */
  }
</style>
siefca commented 1 year ago

The expressive and declarative solution would be to have something like:

<form hx-target="#good"
      hx-target-404="#not-found"
      hx-target-500="main"
      hx-target-50*="#serious-errors">
</form>
1cg commented 1 year ago

that looks like an excellent idea to try out in an extension!

siefca commented 1 year ago

I will try to craft something like that, although I never contributed to JS project before so it will require some review and possibly corrections.

I will need to modify HTMX too to expose some handy functions in its internal API to not repeat what's already there; i.e. searching for closest elements to mimc the behavior of the getTarget() function.

siefca commented 1 year ago

https://github.com/bigskysoftware/htmx/pull/1436

Good Night! :)

siefca commented 1 year ago

Updated the request with tests for response-targets. Tests are passing.