Tips for new TMS Web Core developers and in particular for seasoned Delphi developers

TMS Web Core is an increditble tool for developing web apps using much of the same tooling and knowledge that has become second nature for Delphi developers. But developing a form for a web page is a very different thing than developing a form in a VCL app or even a FireMonkey app. Different doesn't necessarily mean worse, just different. There are quite a few things that are likely to trip up even the most accomplished Delphi developer along the way.

This post is meant as a repository for this kind of thing, so I'd like to invite everyone to add something here that they've run into that might help others along the way. Or maybe a link to another post either here in the TMS Support Center or elsewhere that was helpful in tackling a particular problem. Mostly thinking of simpler just-getting-started kinds of problems here, not esoteric only-ever-applies-to-my-project-on-the-second-full-moon-of-an-odd-numbered-month kinds of problems :slight_smile:

1 Like

I'll offer up one to start.

Tab order in web pages is a different thing than in VCL apps. What I've found, when I have a bunch of edit controls or something, is to just give them an arbitrary set of TabOrder values. So 100-110 or something. So at least when one of them is active, the previous/next tab will go to the previous/next control in that particular set. This works particularly well if you've got controls added to panels or other DIVs where the usual ordering mechanisms don't work partiucarly well at all.

You can't just use a global variable inside an asm block. First, you need to declare a local variable, then you have to pass on the global variable value to the local variable, and then you can use that local variable in the asm block.

2 Likes

I can't remember the exact scenario, but I think it's because of the Optimization option that some of the code doesn't get included in the final build of the project. I noticed this when sometimes the code doesn't work as expected, and when I put a ShowMessage along with the value that I'm having an issue with, it works fine. So what I did was adding something like this inside the code:

if False then
begin
  aa;
  bb;
  cc;
  ...
end;

Doing this forces the compiler to include these blocks and as such the project works as expected again.

1 Like

Yes! I've found this as well, particularly when Delphi procedures or functions are only called by Javascript code, the compiler thinks it isn't used, so it excludes them. Also, when you use variables in a procedure but only in the Javascript code, like in your example about local variables, the compiler issues a Hint about that which is kind of annoying because it is otherwise perfectly valid. I included my workarounds for both of these in a writeup here. I hadn't thought of just wrapping the code in an if-then block, good idea!

Get accustomed to using Timers. After decades of Delphi VCL work, there were maybe a handful of situations where I had any need for Timers (I didn't do much work with multithreading). In TMS Web Core, everything can (or should) be asynchronous when it comes to updating the UI. For example, there's (deliberately) no sleep function but you can use a Timer to work in a similar way, checking for something to change before initiating some other UI update.

FontAweseome is... awesome. Maybe poorly named though, as its purpose is less about fonts and more about icons. Gone are the days spent fiddling with glyphs or trying to cleanup an icon so that it looks good at 16x16 and 256x256.

NOTE: You do have to explicitly add FontAwesome to your project. Lots of options here, but one is to add something like this to your Project.html file:

<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fortawesome/fontawesome-free@5.15.4/css/all.min.css">

Then, wherever you need an icon for something, just add in the FontAwesome tag, typically in the Caption property of a control, and you've got an icon:

LoginButton.caption := '<i class="far fa-sign-in-alt"></i> Login';

There are thousands of icons to choose from, and different styles, and even more with the paid plans. Plenty to work with even with the free option. I particularly like the duo-tone icons included in the paid plan.

But wait, there's more! There are a bunch of things you can add to the classes to change the appearance of the icons. Like modifiers to make the icons larger or smaller. Or offset or rotate them in some direction. And they work with Bootstrap modifiers as well.

You can even make a trivial kind of busy indicator by adding the 'fa-spin' class which causes the icon to spin. Works best with icons that were designed for that purpose:

WaitButton.caption := '<i class="far fa-circle-notch fa-spin"></i> Please Wait';

And you can add multiple icons at one time, overlay them, do all kinds of things. Pretty awesome.

1 Like

I use a TWebTimer and a TWebWaitMessage when closing PopUps (because the close too quickly :-).

So when Save is clicked

SaveTheWork;
TWebWaitMessage.Show;
TWebTimer.Enabled;

Then in TWebTimer.OnTimer

TWebWaitMessage.Hide;
ModalResult := mrOK;
1 Like

Browser debugging tip.

Scenario: You have a dynamically displayed control on the page that only appears after some kind of user action. Like a popup menu or a combobox dropdown or something like that. And you want to use the browser DevTools to look at or test the CSS properties of the control in its activated state. But when you click on the element in the DevTools node tree, the state of the control reverts back and you can't see the properties you're after.

One option is to use the DevTools console to trigger a debug event after a short delay. Just paste this into the console and hit enter. You'll have a three second delay before the debugger pauses, giving you enough time to bring up the menu or click on the combobox to show the dropdown. You can then look at that element's properties, adjust settings, and so on, without it reverting back to its normal state.

setTimeout(function() { debugger; }, 3000);

Of course you can also adjust that 3000 to something larger if you need more time to select the appropriate control.

1 Like

Right Aligning Text in TWebDBTableControl with Bootstrap

The table control ignores the alignment settings on the dataset fields. So if you want to align right for numbers, then set the TWebTableControlColumn.ElementClassName := 'text-end'

1 Like

Perhaps another tip is just that new TMS Web Core projects in general benefit greatly from the use of Bootstrap to begin with. It is helpful that TMS Web Core recently started including a new project template specifically for Bootstrap. I frequently use this Bootstrap Cheatsheet as my go-to resource for looking up bootstrap classes. Are there any other good recommendations other than of course the Bootstrap site?

There are also other examples here in the Support Center such as here and here that relate to where Bootsrap can come in handy in TMS Web Core, in addition to the above post of course.

1 Like

Naming Element Id

If you are using popups, make sure that the element ids are not just unique within the popup but within the form that popup is displayed on.

2 Likes

TWebWaitMessage

If you use the TWebWaitMessage.URL property remember to clear the Picture property otherwise the picture will be created in the project output.

1 Like

Upgrading TMS Web Core to the latest version

When installing a new version of TMS Web Core, it is best to first completely remove the old version using the usual Windows Add/Remove Programs process, naturally while Delphi is not running of course. Then install the new version of TMS Web Core as basically a fresh install. There can be problems if this isn't done, as can be sen in a number of posts here in the Support Center over the past while.

It is also a good idea to pay attention to the release notes so that you can check your app for any areas that may be impacted. While my personal experience with updates has been overwhelmingly positive, meaning nothing has broken as a result of an update, there have been instances where some small touches were needed to adjust alignments or that kind of thing. Also good to do a quick review of your app after an update just to make sure there are no surprises down the road.

1 Like