Site icon Embarcadero RAD Studio, Delphi, & C++Builder Blogs

Harnessing the power of the Web with Delphi & HTMX

rad htmx part1 blog image

If you ever wanted to create a server-based web application, then HTMX is a solution that offers great flexibility for development, allowing RAD Studio developers to deliver the business logic while still allowing designers to make the web application look great using CSS. Without having to write a single line of JavaScript code, you can build a full web application, with the entire logic in a web server. And what would be the best language for such a web server? Of course, it’s Delphi.

In this post, we’ll talk about the popular HTMX library and its integration with Delphi. We will also see a very basic demo of a web application running entirely on Delphi code using the WebBroker, with HTMX for the server-side requests.

What is HTMX?

HTMX is a JavaScript library, but it can just as well be seen as an HTML extension, since all of its logic happens in HTML, without the need to write JavaScript. It is most often used as an alternative to JavaScript frameworks like React, Angular or Vue, but uses a fundamentally different approach, which is AJAX requests. With AJAX (or Asynchronous JavaScript and XML), web applications can send and retrieve data from a server asynchronously, without having to interfere with the web page itself and without having to reload it. HTMX allows us to send data from the web page to a web server and retrieve HTML code as a response, which can then be replaced inside the web page.

The idea behind the strategy is for the most part to be independent of JavaScript. By using HTMX no (self-written) JavaScript code is involved, and instead all of the logic of the application happens on the server side. This has plenty of advantages, including privacy and the ability to use existing codebases, no matter which programming language. The separation of the logic from the web is also something many developers appreciate.

Why use HTMX with Delphi?

HTMX offers the opportunity to write entire web applications, with all of the logic in a web server. The web server can be written in any programming language you want, as long as it is fast and efficient. The best choice for such a web server is Delphi, since it is highly-capable, object-oriented and one of the fastest languages on the market.

The most potential of this technology for Delphi developers does not necessarily lie in writing new applications, but in putting old VCL codebases in a web server and using those for writing web applications. This way Delphi desktop applications can be fully migrated to the web, without needing to rewrite all of the code in JavaScript, which saves huge amounts of time and effort.

Step 1: Creating the web server

Creating the web server as a console application with the WebBroker is very straightforward. In RAD Studio select File > New > Other. In the new Items dialog box, select the Web tab under Delphi and select Web Server Application. Windows will be the default platform and you can additionally select Linux. Go next and select console application, then finish. Save the project in a path of your choice and your web server is ready to go. Compile and start the server, then a terminal window will open. Enter “start” and the server will be accessible under the port that you entered (default is 8080). Open localhost:8080 in a browser and you should see your app.

Step 2: Preparing the HTML and HTMX

The outer canvas of a web page is shaped in HTML. So let’s create a simple HTML page. Create a file index.html and paste the following.

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8"/>
        <meta name="viewport" content="width=device-width, initial-scale=1.0"/>
        <title>Delphi & HTMX Demo</title>
        <script src="https://unpkg.com/htmx.org@1.9.12"></script>
    </head>
    <body>
    </body>
</html>

Notice the <script src=”…”></script> line. This is the only thing we need to include HTMX in our project. No need to download anything, just add this line and HTMX is ready to go.

In order to display the index.html the web server needs to return the contents of the file. The default handler is located in the unit WebModuleUnit1.pas, where there is already a plain HTML template returned. Let’s replace this with our index.html file:

procedure TWebModule1.WebModule1DefaultHandlerAction(Sender: TObject;
  Request: TWebRequest; Response: TWebResponse; var Handled: Boolean);
begin
  Response.Content := TFile.ReadAllText('index.html'); //full path to the file
end;

Here you either have to use the absolute path to the file or copy the file to the destination dir. Recompile and restart the server and you should see our empty HTML page.

Step 3: Hello World

Let’s fill our page with a little bit of life with a simple “Hello World” example. The goal is to have a label and a button, and by clicking the button the caption of the label will be “Hello World”. So, first add a label and a button to the <body>.

<h1 id="header">Delphi & HTMX Rocks!</h1>
<button hx-get="/helloworld" hx-target="#header">Click me</button>

Notice the hx- attributes. This is our HTMX “code”. What this basically means is when the button is clicked, execute the GET-Request /helloworld and put the response into the caption of the label. So, the next step is to implement the GET-Request in the server.

For this, navigate to the object inspector in the designer and open the actions editor. There you can create a new action, select mtGET as the method type, give it a name and enter /helloworld for the PathInfo. Navigate to events and create a new event for it. You should have an event like this:

procedure TWebModule1.WebModule1HelloWorldAction(Sender: TObject; Request: TWebRequest; Response: TWebResponse; var Handled: Boolean);
begin
end;

Now we are just going to return “Hello World” as a response.

Response.Content := 'Hello World!';

Your first Hello World app is finished! See how straight-forward web development can be? Let’s take this a bit further.

Step 4: A step further

The goal now is to have an edit and a button. The edit is read-only, but when the user clicks the “Edit” button the edit becomes editable and the “Edit” button changes to a “Submit” button. After clicking “Submit”, the entered text in the edit will be the caption of another label. First, the HTML:

<form hx-get="/edit" hx-swap="outerHTML">
    <input type="text" name="edit" readonly/>
    <button>Edit</button>
</form>

What we have here is a form with an (read-only) edit and an “Edit” button. When the button is clicked, a GET-Request along with the value of the edit will be executed. The result will be HTML, which is going to replace the entire form. In HTMX, this is called a “swap”. Let’s implement the /edit request. First, create an action, just like we did in Step 3. In the request we want to read the value of the edit and replace the entire form with HTML. The HTML will simply be a string constant, for which we can use one of the best features of Delphi 12, the multi-line string literals.

procedure TWebModule1.WebModule1EditAction(Sender: TObject;
  Request: TWebRequest; Response: TWebResponse; var Handled: Boolean);
const
  cEdit = '''
    <form hx-post="/submit" hx-swap="outerHTML">
        <input type="text" name="edit" value="%s"/>
        <button>Submit</button>
    </form>
  ''';
begin
end;

The HTML there is nearly the same as before, but the edit is not readonly and the “Edit” button is now a “Submit” button. Additionally we now have a POST-Request called “/submit” and we format the text from before in the new edit. Of course, at the beginning this will be empty.

var
  lResponse: string;
begin
  lResponse := Request.ContentFields.Values['edit'];
  Response.Content := string.Format(cEdit, [lResponse]);
end;

lResponse reads the next from before, which we included in the GET-Request and we format this into our response. 

Now the POST-Request /submit. Add an action like before, now with mtPOST as MethodType. First declare a constant for the HTML to return, which will be the same that we wrote into the index.html file.

procedure TWebModule1.WebModule1SubmitAction(Sender: TObject;
  Request: TWebRequest; Response: TWebResponse; var Handled: Boolean);
const
  cSubmit = '''
    <form hx-get="/edit" hx-swap="outerHTML">
        <input type="text" name="edit" value="%s" readonly/>
        <button>Edit</button>
        <label>%s</label>
    </form>
  ''';
begin
end;

Notice the label. There we are going to format the edited result in. Now do the same as before.

var
  lResponse: string;
begin
  lResponse := Request.ContentFields.Values['edit'];
  Response.Content := string.Format(cSubmit, [lResponse, lResponse]);
end;

If you want to try the demo yourself you can find it in our GitHub repo. Keep in mind that it will only work with Delphi 12.0 or above.

 

That was it! Recompile and restart and you will see the results. Click “Edit”, enter a text in the edit control, click “Submit” and the entered text will appear in a label.
We are working on another blog post where we will make this same demo look more modern and up-to-date with just a few changes using the library PicoCSS. Here’s a sneak peek of how it will look. Stay tuned!


Article written by Elias Kassebaum.

Exit mobile version