Run

These directions support both using a web server, or  IWML Runner.

via IWML Runner

Before proceeding, please read this topic to learn how IWML Runner works.

IWML Runner makes it quick and easy to run IW17 applications. For this tutorial locate Apps\Guess\index.iwml and double click it in Explorer.

IWML Runner will then launch the Guess application in the browser.

via Web Server

Now that you have IntraWeb 17 installed, let’s see how to run the samples. Web browsers cannot directly consume .iwml files and need .html loader pages.

If you installed correctly, open a browser and enter this URL:

http://127.0.0.1/IW17/

A window similar to this should appear:

As we are constantly expanding the samples, screenshots may not look exactly as seen here. Because IntraWeb 17 releases are currently internal development snapshots bugs and unfinished features should also be expected.

This is a static HTML (index.html) file with links to individual applications. At the core of any IntraWeb 17 page is IWML. IWML can be dynamically generated and will be from a Delphi server in IntraWeb 17, but for now the IWML comes from static .iwml files. In IntraWeb 17, IWML replaces HTML in most roles.

For this tutorial, select the Guess link to proceed.

Good Old Guess Demo

Let’s take a look at a very simple Guess demo to explain the parts of a basic IWML front end application. Click the Guess link.

The first thing to notice is that it is not fancy or glitzy. It is not supposed to be as we want to demonstrate just bare mechanics at this point. IWML is turned into HTML though and fully able to be styled so glitz can easily be added to any IW17 page.

In fact IW17 already supports JQueryUI out of the box and will support many more JavaScript libraries.

The application functions as expected:

The Parts

At a bare minimum, an IW17 page needs an .iwml file or a server process to send .iwml to the browser. The .iwml is kind of like a Delphi .dfm for the web. IWML is transformed into HTML in the browser by the IWCL (IW Component Library).

An IWML file however only handles the display aspect. While IWML does support data binding and can display and even update data in some cases, if you need functionality in most cases you will need to add code as well.

When complete you will be able to add code either in TypeScript, or in Delphi on the server side as you can now with IntraWeb and IWML will be fully integrated into the Delphi IDE. For now however, all code is written in TypeScript, but server calls are coming soon and you can use Delphi as a REST server to connect to IW17 on in the browser.

To launch your IW17 page you will need an HTML file to help load the libraries and the IWML page. When integrated with Delphi, IntraWeb will generate this HTML transparently for you as it does now, or you can still use HTML generated from another source or a static HTML file as is done currently.

One HTML file can serve up many IWML files, so you do not need to create a separate HTML file for each and every IWML file. Typically we create one HTML file per application, which is a collection of of IWML and TypeScript code files.

Guess as it is now contains three files as detailed previously:

TypeScript compiles to JavaScript, so when the project is built there will be two additional files in the directory:

When debugging, all files are needed. However when deploying the .ts and .js.map files are not needed. These two files are only needed for debugging. When deploying without debugging, only the .html, .js, and .iwml files are needed.

How It Works

Let’s dive into the details of what happens behind the scenes.

Index.html

Index.html loads the .iwml file, and optionally a TypeScript code file. Index.html from Guess is an unmodified generic IW17 loader.

<!DOCTYPE html>

<html lang="en">
<head>
  <title>Root Index</title>
  <meta charset="utf-8" />

  <meta http-equiv="Pragma" content="no-cache">
  <meta http-equiv="Expires" content="-1">
  <meta http-equiv="CACHE-CONTROL" content="NO-CACHE">

  <script src="/IW17/IntraWeb/Loader.js" data-AllowDocParams="true" data-Source="*"></script>
</head>

<body>
  Loading IntraWeb...
</body>

</html>

Everything is standard HTML, and the only addition required is a single script tag which loads the IntraWeb libraries. By default the libraries will look for an accompanying .iwml file to match the .html file name. In this case since the .html file is index.html, the library will look for an index.iwml file.

This default behaviour can be overridden with a URL parameter to allow a single .html file to serve any .iwml file.

Index.iwml

Index.iwml provides the interface that the user sees. For Guess, the IWML is pretty basic although IWML is capable of 2 way data binding, REST integration, advanced layouts, and much more.

ACORN 1.0 IWML 1.0
Guess.Index
  FocusControl: GuessEdit
  ActionControl: GuessButton
  Root[]
    SimpleStack[]
      Edit:GuessEdit;
      Text:MsgText;
      TextBlock[]
        Text Guess #
        Text:CountText 0
      ]
      Button:GuessButton Guess
    ]
  ]
]

As shown previously, this IWML renders as shown here:

Index.ts

Index.ts contains the TypeScript code for Index.iwml. IntraWeb automatically looks for an accompanying file and loads it if necessary. Currently TypeScript code is hand written, but in the future much of it will be generated transparently for you just as IntraWeb does currently with JavaScript, and will allow you to mix in your own custom code if needed.

namespace Guess {
  export class Index extends IntraWeb.Code {
    public GuessButton: IntraWeb.Controls.Button = null;
    public GuessEdit: IntraWeb.Controls.Edit = null;
    public MsgText: IntraWeb.Controls.Text = null;
    public CountText: IntraWeb.Controls.Text = null;

    protected _MagicNo = Math.floor((Math.random() * 100) + 1);
    protected _Count = 0;

    public Page_AfterLoad(): void {
      const xMagicNo = this._Page.WebParam("MagicNo");
      if (xMagicNo !== null) {
        this._MagicNo = parseInt(xMagicNo, 10);
      }
    }

    public Event_GuessButton_Click(aSender: object, e: MouseEvent): void {
      if (e.shiftKey) {
        IntraWeb.Dialogs.MessageBox("The magic number is: " + this._MagicNo);
        return;
      }

      let xMsg: string = null;
      const xGuess = Number(this.GuessEdit.Text.Value);

      if (isNaN(xGuess)) {
        xMsg = this.GuessEdit.Text.Value + " is not a valid number.";
      } else if (xGuess < 1 || xGuess > 100) {
        xMsg = xGuess + " is not in the range of 1 to 100.";
      } else {
        this._Count++;
        this.CountText.Text.Value = this._Count.toString();

        if (xGuess < this._MagicNo) {
          xMsg = xGuess + " is too low.";
        } else if (xGuess > this._MagicNo) {
          xMsg = xGuess + " is too high.";
        } else if (xGuess === this._MagicNo) {
          IntraWeb.Dialogs.MessageBox("Congratulations! You guessed the magic number.");
          this.GuessButton.Enabled.Value = false;
        }
      }

      if (xMsg !== null) {
        this.MsgText.Text.Value = xMsg;
      }
      this.GuessEdit.Text.Value = "";
    }
  }
}

As you can see, TypeScript is not too dissimilar from Delphi. And when IW17 is ready, you will not need to write TypeScript anyway but can write normal Delphi code and IW17 will do the translations into TypeScript for you to mix client side generated TypeScript with Delphi server side code.

Let’s Code!

If you like what you see, proceed to Development Quick Start.