Using more complicated templates

A lot of templates would have multiple nicely arranged areas/DIV's in the main part/DIV of the page. I've tried hooking up to a few of these sub-DIV's without breaking the overall design of the page, but failed: the Form needs to be pointed to an area with FormContainer, so if I point it to the outer DIV of the main part of the page, it occupies it and all sub-DIV's are effectively gone. And if I point it to any of the sub-DIV's, then I can essentially have a single control, like a Chart, maximized to the entire Delphi form and this kind of works, but then I'll end up with 10 forms open at the same time, each shown in a sub-DIV, plus I could not control form/DIV sizes in this way, so the page layout was destroyed.

Sorry if that's not very clear, I'm new to Web Core. But say you have a template like this:

How would you do the Delphi side of things to replace the charts and fill in the label values and lists, keeping it all as it was designed in the original HTML page?

Or would the entire page need to be redone in Delphi instead, with a single Form, where you would lay your controls out in a similar fashion? - this is how it looks like in the Template sample project.

Trying to replicate page layout with TWebHTMLDiv controls does not quite work for me either: position Ignore scrambles them, Relative is not quite what I'd expect either, for instance it adds extra "box-sizing: border-box;" attributes I did not ask for:
(the following HTML may not display, even escaped)

<div id="TForm21_HTMLDiv2" zindex="0" class="col-lg-4" tabindex="-1" role="" style="position: relative; box-sizing: border-box;">...</div>

And it appears to have redone my design: dropped a DIV or two and moved a bunch from one DIV to another...

If you're new to TMS WEB Core, welcome aboard! There's a lot to understand about how TMS WEB Core connects Delphi apps to typical HTML templates and web apps in general, so be sure to have a look through some material first if you're interested in getting a bit more of a footing from those that have come before you...

  • This post in the TMS Support Center
  • There is a set of "Basics" posts (ongoing!) in the TMS Blog, starting with this one.
  • There are numerous other blog posts and even some books by Holger Flick to help things along.

With that out of the way, I'm hoping you're referring to the Template Project that was written about in this blog post (or this GitHub Repository). I created it, so I can hopefully help you understand how it works. Note that this is not exactly the simplest project to start with.

But before we get to that, here are a few notes on how HTML Templates work with TMS WEB Core.

In the simplest TMS WEB Core project, there is a Project1.html file, a Unit1.pas Delphi file, and a Unit1.html file. Typically each Form within Delph is associated with an HTML file, though this is no longer strictly required (referred to as Direct Forms).

Generally speaking, an HTML file is loaded up as part of the Form, and its contents are inserted into the <body> of the document which is essentially what is found in the Project1.html file. The HTML elements of the Unit1.html "template" can be combined with the Unit1.pas (and related Unit1.dfm) Delphi Form components by linking them, pairing the HTML "id" properties in the template with Delphi components dropped on the Form, via the ElementID property using the Delphi Object Inspector or one of the linking mechanisms (right-click on the Form, etc.).

When this method is employed, the Delphi component largely replaces the element in the template with whatever the Delphi component is. This works pretty well when the element in the template doesn't have any children, as this replacement doesn't deal with that scenario. It works best with typical TMS WEB Core TWeb components like TWebLabels TWebEdits and that sort of thing, but any TMS WEB Core-enabled components will work just as well.

When it comes to <div> elements, this is probably not what you want to do most of the time, as in an HTML document, those <div> elements are often used to provide structure to the page. You can still easily reference them from Delphi, particularly if they have an HTML "id" assigned, but you don't necessarily want to link them to something like a TWebHTMLDiv component in your Delphi Form unless they don't have any children. There's also usually no need to - you only need to link components to the HTML elements that you want to replace. Maybe a small handful much of the time.

Most often, you'd take a complete template, such as the AdminLTE template in your screenshot, and as used in the Template Project, and then just replace the elements in the HTML template with Delphi components that you want to update. So title captions, footer labels, that sort of thing. Works great.

The AdminLTE template is a bit more advanced though, often with many levels of nesting using those pesky <div> elements. It is also structured by default to have completely separate pages for each one of its examples.

To make the most of this in Delphi, what I set up was multiple forms that are dynamically loaded (sometimes nested) into one another as the user navigates around the user interface. In this case, the equivalent of the Unit1.html file associated with a Form isn't really a complete HTML page, but rather just the HTML snippet that needs to be loaded into a particular part of the overall page structure. Because the snippet was taken from the AdminLTE template, it includes the same <div> elements and classes that allow the snippet to flow (and be themed) nicely with the rest of the page.

The Template Project starts with a main Delphi Form that encompasses the entire page and loads up whatever is commonly needed by the template in terms of libraries, fonts, and so on.

This Form then loads a second-level Delphi Form that contains things like the header and footer, the main menu, and that sort of thing. In the Delphi side of that Form, there are components linked to the HTML ids that came originally from the AdminLTE template, so that they are a little easier to access from the Delphi side, but this is more for convenience in coding.

This second-level Form then loads the third-level Delphi Form which then provides the detailed content for a given page, like the charts and other sections that you see in the main part of your screenshot and other screenshots for the AdminLTE template. Here, again, a subset of the entire page's HTML is linked to a Delphi Form, and the relevant bits are paired up between Delphi components and HTML id elements. This makes things a little easier to manage as you can build a pretty complex website with dozens of these little subforms rather than trying to build a big monolithic page within one Delphi Form.

Each level (the main page, the "dashboard" level below it, or these individual "subforms") contains whatever pieces are necessary to tie together the menu navigation and other common elements and allow for the dynamic loading and unloading of Forms from the page overall. So if you're looking at a page with a chart on it, the potentially dozens of other pages with other charts are not currently loaded. They are loaded and unloaded as needed, via functions defined in one of these Forms.

It's a bit complicated and is quite different from how the AdminLTE template works normally, but it is just a template. In the Template Project, we just copy the sections of the AdminLTE template we're interested in, into the various Delphi Forms (the Unit.html files) as we go about creating different sections of the app. We're careful to copy all of the parts of the template that are relevant, including all the class names and the <div> structure, sometimes adding in more HTML id attributes where they are missing.

Hope that makes some sense. Happy to help further if it doesn't!

Thanks, Andrew. Indeed this is the case and I'm busy going through those posts and docs in parallel.

What I tried with DIV's was not to link them, but rather delete all original ones in HTML and add mine, following the same structure and setting same class names to get the styles right. But the end result was essentially scrambled. And pas2js has been adding unwanted attributes to those DIV's as well, which was unexpected.

I could next try to replace this structure with a floating DIV layout on the form, following similar design strategy, but without relying on their styling.

You are referring to an existing project that you have built for this scenario, is that something that may be available / you could share as a sample?

1 Like

Yes, check out the GitHub link - you can download the complete source code from there.

When using a template, often it is easiest to just copy the entire template into Unit1.html (or whatever your Delphi unit is called) and just add the Delphi Form component links to the HTML elements that are of interest. Often, you might have to add id attributes to the HTML elements as they aren't always given an id to begin with in the template.

The other thing is that templates often come with additional CSS or JavaScript files. It may be most convenient to take those references from the HTML template and add them to the Project1.html file (or whatever your project's HTML file happens to be called). This helps ensure that those resources are only loaded once for the project.

You can then simplify the copy of the template in Unit1.pas by taking out the header stuff (that has been copied to Project.html) and removing any other bits you don't need.

But by default, if you've copied the template successfully, the page rendered by TMS WEB Core will look exactly like the original HTML template, before you do any of the component linking. This is because the resulting HTML being generated should in fact be largely identical. At least the bits in the body element.

If that's not the case, then something in the original HTML template isn't making it on to the page, and that would need to be sorted out first.

You also have to be careful with templates and their related CSS files as sometimes they may reference elements on the page in unexpected ways. For example, you might see CSS that references something like this:

#ParentElement > div > div > .class1 > div {
  someproperty: somevalue;

If you've removed #ParentElement, or one of the nested <div> elements, or changed where class1 appears in the hierarchy, the CSS might not be applied successfully.

That's why its best to start with the entire template copied into Unit1.html and then remove bits you don't want one at a time, being sure to check that the rendering of the rest of the page isn't completely messed up when you do that.

Keep in mind that even a little bit of CSS applied (or not applied) can have a dramatic impact on the layout of the page.

How did you make out? Were you able to get your template loaded with the changes you wanted?

I had a look at this demo, but I thought this was a bit complicated. I'm now trying to replicate DIV layout on the page in Delphi: I have deleted all HTML content in the centre of the WEB page and plugged in my Delphi Form there with a single FormContainer link to the page. Then on the form, I'm creating nested TWebHTMLDiv's, not linked to anything on the (now empty) page, but setting Div styles as per the original HTML design. And it's actually working quite nicely. A bit fiddly, of course.

Unfortunately, running this in Delphi debugger has stopped producing output for me: I get a blank webpage with a spinning wheel in the browser now. But running the EXE manually outside of IDE works. Which is Ok for the moment, but if I run into any issues, I won't be able to debug it. Have you seen anything like this? It's D11.3.

But back to the template: it's all still experimental for me, so I'm figuring out what I want displayed and where as I go along. And then I'll need to develop XData services, Aurelius schemas at the back and add Sphinx on top, so it would be a long road.

1 Like

Sounds like you're on your way :+1:

The Template Project is not really a good choice for a first TMS WEB Core project as it is indeed complicated, mashing together quite a number of things that are themselves already pretty complicated.

One of the Basics posts covers debugging, but it is also an area that has been getting a lot of attention from TMS since that blog was written, with one of the most recent updates bringing debugging back into the IDE. I'm pretty comfortable just using the browser debugging tools without the IDE integration stuff, so I'm not all that familiar with these new changes. Should work fine under D11 though.

CSS is always a bit fiddly, nothing much can be done about that. Not really anything to do with TMS WEB Core of course - that is just how CSS works.

And your last comment is perhaps the most accurate - often things that seem pretty trivial actually are pretty trivial once you've gotten a few examples working and you're familiar with how things work. But there can be a LOT of moving pieces and the first project or two can be pretty daunting. It's a very different world than, say, the VCL.