Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Question] Option to override xhr request with call to my SDK #2536

Open
7flash opened this issue May 9, 2024 · 7 comments
Open

[Question] Option to override xhr request with call to my SDK #2536

7flash opened this issue May 9, 2024 · 7 comments

Comments

@7flash
Copy link

7flash commented May 9, 2024

I understand htmx works best with REST but in my case there is black box SDK in between, therefore I am trying to override beforeRequest to handle form submission with my SDK, wrap it with HTML response and then proceed as normal, can it work?

htmx.on("htmx:beforeRequest", async function(evt){
	const response = await window.my_sdk(evt);
	return `<h1>${response}</h1>`
})
@7flash
Copy link
Author

7flash commented May 9, 2024

#340

@7flash 7flash changed the title [Question] Option to override xhr request #340 [Question] Option to override xhr request with call to my SDK May 9, 2024
@7flash
Copy link
Author

7flash commented May 9, 2024

Second alternative, I considered using a service worker which implements SDK interactions

@7flash
Copy link
Author

7flash commented May 9, 2024

Third alternative, I tried to override XHR with Proxy

XMLHttpRequest = new Proxy(XMLHttpRequest, {
      construct: function (target, args) {
        const xhr = () => my_sdk;
        return xhr;
      },
    });

@Telroshan
Copy link
Collaborator

Hey, if you're making a call to a black box SDK, that apparently doesn't return an HTML response, will probably not use any of the htmx features such as response headers, you might be better off simply not using htmx in this case and process the response yourself, from a standard form's submit default-prevented event, in your JS.

@7flash
Copy link
Author

7flash commented May 12, 2024

I believe htmx allows me to write more clean code

Look at this example of using my SDK (backend) with lit framework:

import { html, render } from 'lit-html';
import { backend } from 'declarations/backend';

class App {
  greeting = '';

  constructor() {
    this.#render();
  }

  #handleSubmit = async (e) => {
    e.preventDefault();
    const name = document.getElementById('name').value;
    this.greeting = await backend.greet(name);
    this.#render();
  };

  #render() {
    let body = html`
      <main>
        <form action="#">
          <label for="name">Enter your name: &nbsp;</label>
          <input id="name" alt="Name" type="text" />
          <button type="submit">Click Me!</button>
        </form>
        <section id="greeting">${this.greeting}</section>
      </main>
    `;
    render(body, document.getElementById('root'));
    document
      .querySelector('form')
      .addEventListener('submit', this.#handleSubmit);
  }
}

export default App;

With htmx it can be more concise just like this:

      <main>
        <form hx-post="/greet" hx-target="#greeting">
          <label for="name">Enter your name: &nbsp;</label>
          <input id="name" alt="Name" type="text" />
          <button type="submit">Click Me!</button>
        </form>
        <section id="greeting"></section>
      </main>

@Telroshan
Copy link
Collaborator

Well, looking at those exact snippets, it would seem that the htmx version is cleaner & more concise.
But is it? Because in that second scenario, as you mentioned above you would have to add code elsewhere to intercept, mock the requests and return HTML from your JS to have the swap happen. So it would not just be that little html snippet compared to the first one that is on the other hand self-sufficient.

Plus, you oppose it with a framework's syntax that has a lot of boilerplate code compared to the actual logic, so it feels like an unfair comparison here. With vanilla JS, it would be like this

<main>
  <form id="myForm">
    <label for="name">Enter your name: &nbsp;</label>
    <input id="name" alt="Name" type="text" />
    <button type="submit">Click Me!</button>
  </form>
  <section id="greeting"></section>
</main>

Note that this HTML didn't change much from your second more-concise approach, I just removed the hx attributes as we won't use it (not use htmx at all) and added an ID to the form to retrieve it easily

document.getElementById("myForm").addEventListener("submit", async function(event) {
    event.preventDefault();
    const name = document.getElementById('name').value;
    const greeting = await backend.greet(name);
    document.getElementById("greeting").innerHTML = greeting
})

Now, would that still be a "less concise" approach than what you would have to do to mock this SDK behavior and make it act as it was a XHR request? I would really doubt so.
Out of the 5 lines of code above, you would still need to extract the name from the payload, you would still need to call the SDK and you would still need to return a HTML response to be swapped in. So it seems like the only lines of code you'd save are the
submit event binding and the preventDefault call, which really doesn't feel like a win to me, given the complexity to reach what you were trying to do

@7flash
Copy link
Author

7flash commented May 19, 2024

Actually I succeed on this using Service Worker as in example of POST request in htmx form below:

https://github.com/galaxydo/ic-sw-starter/blob/fed15d9b3bfba91d499e2816340fd4808ee95a52/src/may16-galaxy-frontend/src/pages/Index.tsx#L12

It's being intercepted by SW here which handles the request and responds with HTML as a proper backend would do

https://github.com/galaxydo/ic-sw-starter/blob/fed15d9b3bfba91d499e2816340fd4808ee95a52/src/may16-galaxy-frontend/src/index.tsx#L108

But in this scenario, since we are building dapp, we try to avoid using any centralized server, yet by moving the backend with SSR to the edge in SW, we can still enjoy all benefits of proper hypertext with HTMX.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants