Page Properties

Page Properties

Now we will expand using a very powerful feature called page properties. Page properties allow for easy communication between Delphi, Client IWML, and client script.

Previously we used _GuessCount and _MagicNo. We will continue to use them, but we will upgrade them to be published properties:

type
  TUnit1 = class(TIW17Page)
    GuessEdit: T17Edit;
    MsgText: T17Text;
    CountText: T17Text;
    GuessButton: TBSButton;
    Accordions: TJQUIAccordionGroup;
    procedure GuessButtonClick(aSender: T17Renderer);
    procedure IW17PageCreate(Sender: TObject);
  private
    _GuessCount: Integer;
    _MagicNo: Integer;
  public
  published
    property GuessCount: Integer read _GuessCount write _GuessCount;
    property MagicNo: Integer read _MagicNo write _MagicNo;
  end;

In GuessButtonClicked, remove this line just before the final end:

Modify the PageCreate event to remove _GuessCount initialization (let it remain at 0):

procedure TUnit1.IW17PageCreate(Sender: TObject);
begin
  _GuessCount := 1;
  _MagicNo := Random(100) + 1;
end;

Data Bind to Page Property

Modify CountText.Text to the following value:

Guess #[=prop.GuessCount]

Using the designer:

From the user perspective, nothing has changed. Our application functions the same. Instead of using server code to update the Guess count, we now are using data binding.

=prop.GuessCount tells the IWML to bind to the new server side GuessCount property that we made:

property GuessCount: Integer read _GuessCount write _GuessCount;

The value is automatically synchronized and updated. When we increment it in our Click event, the IWML is also updated with the value:

Inc(_GuessCount);

Two Way

The binding isn’t one way – it’s two way. If we update the properties in Delphi, they are updated in the client. If we update them in the client, they are updated in Delphi.

Page properties are always accessible via the .Properties property of the page. However we can make them even easier to access by adding matching properties into our client event.

Modify GuessButton’s ClientEvents.Clicked:

(aSender, aArgs) {
  this.MsgText.Text.Value = '';

  if (aArgs && aArgs.shiftKey) {
    window.alert(`The magic number was ${this.MagicNo}, it is now 22.`);
    this.MagicNo = 22;
    return;
  }

  let xGuess = Number(this.GuessEdit.Text.Value);
  if (isNaN(xGuess)) {
    this.MsgBox.Show(this.GuessEdit.Text.Value + ' is not a valid number.');
    this.GuessEdit.Value = '';
  } else if (xGuess < 1 || xGuess > 100) {
    this.GuessEdit.Value = '';
    this.MsgBox.Show(xGuess + ' is not in the range of 1 to 100.');
  } else {
    this.CallServerEvent();
  }
}

Now if we press the shift key when we click Guess, our client script will not only tell us the magic number, but it will change it. Note that we check the guess against the magic number in our server code. Since when we execute this.MagicNo = 22 in client script, IntraWeb automatically synchronizes the value on the server side, we can retain our server side check:

  end else if xGuess = _MagicNo then begin
    MsgText.Text := 'Fantastic! You guessed it in ' + GuessCount.ToString + ' guesses.';

We can modify the property in the client, or on the server and IntraWeb takes care of the rest.

If we run our application and hold down the shift key when we press the Guess button:

UI Separation

You can even add an additional Guess property, bind the Edit control to it, and then in our Delphi code simply get and set .Guess, instead of needing using the Edit.Text property.

Using these techniques you can easily and completely isolate your UI from your code.

JavaScript Library Integration

While this tutorial shows this functionality in conjunction with IWML controls, this feature can be used to talk directly from JavaScript libraries inserted into templates and your server side Delphi code without needing to implement an IWML control. IWML controls are very easy to create, however often it is simpler to integrate with existing  HTML templates which load JavaScript libraries on their own if you are already doing things this way from earlier versions of IntraWeb or for other reasons.

Isolated JavaScript can access IntraWeb easily by using:

IntraWeb.App.CurrentPage

This will return a reference to the currently displayed Page. From the page, everything else in IntraWeb can be accessed and is not limited to page properties. To access page properties for example:

let x = IntraWeb.App.CurrentPage.Properties.MagicNo;

See Also