Windows and Web integration through Thinfinity® jsRO (Javascript Remote Objects) – Part 3

Now that we’ve learned how to create a remote object and expose it on the Web, let’s see how to interact with jsRO objects in more detail.

 

The jsRO Object life cycle and the predefined Javascript Events

Let’s begin by noting that the jsRO objects are always defined inside the application and propagated to the browser. You can’t add new properties, methods or events to these objects in the browser side, but you can retrieve and modify property values, invoke objects’ methods and handle their events.

Four predefined Javascript events are related to the jsRO object life cycle, associated to its creation, updating and destruction.

Starting from the first ApplyModel invoked in the application, jsRO will create the object and propagate it to the browser, where it will trigger the created event:

on(“model:object”, “created”, ...)

also, for the properties that are created with an assigned value, jsRO will replicate their initial values in the browser and fire the corresponding events (one per property):

on(“model:object.property”, “changed”, ...)

and from that moment on, it will keep the state of the properties in the application and the browser synchronized with each other.

If the model needs to be updated by the addition of new attributes (such as new properties, events or methods) a new ApplyModel must be invoked, which will, now that the model has been created, fire a changed event on the model.

on(“model:object”, “changed”, ...)

Finally, if the object is destroyed in the application, the deleted event will be triggered and the object will be destroyed in Javascript too.

on(“model:object”, “deleted”)

This last event will also be triggered when closing the application.

Javascript "Model" Events

The opposite direction: OnPropertyChange(), OnSet() and OnGet() events

When publishing a model, jsRO will keep the created object’s state in the application and the browser side synchronized with each other. Each time a property is updated in the application side, this change fires an event to the browser, where, in addition to updating the value, it can be handled by the corresponding .on(“model:object.property”, “change”, …) event, if it has been declared.

When a property is updated on the browser side, this change is sent in the opposite direction (that is, from the web to the application) and triggers an OnPropertyChange event in the instantiated JSObject object. This  would be a good place to do things like propagating the change of a property’s value to some other element of the application, updating a group of values in a database, etc.

jsRO can also handle changes in its objects’ properties through the declaration of the OnSet and OnGet property events.

By invoking the ApplyChanges method on a JSObject object, its properties collection is traversed and any declared OnGet event is triggered.

Using Property OnGet

Whenever the value of a property is modified in the browser this change is propagated to the same property in the application side. If in the application the modified property has the OnSet event defined with its corresponding callback, the callback will be executed.

Using Property OnSetThe way to add the OnSet and OnGet event handlers to a property is based on their definitions.  It can be done when adding the property or afterwards, but always remember to invoke the ApplyModel method so that the model is propagated to the browser.

The following example shows how the browser can retrieve the application form background color in the #RRGGBB format, and also how to change the background color using a value sent from the browser. Since the desktop application doesn’t interpret colors the same way the web does, we need a conversion that works both ways.

The Delphi code for this example is:

// Creates the remote object
FRo := TJSObject.Create('ro');

// Property definition
FRo.Properties.Add('backgroundColor')
   .OnGet(TJSBinding.Create(
      procedure(const Parent: IJSObject; const Prop: IJSproperty)
      begin
         Prop.AsString := '#'
            + IntToHex(GetRValue(ColorToRGB(Form1.Color)), 2)
            + IntToHex(GetGValue(ColorToRGB(Form1.Color)), 2)
            + IntToHex(GetBValue(ColorToRGB(Form1.Color)), 2);
      end))
   .OnSet(TJSBinding.Create(
      procedure(const Parent: IJSObject; const Prop: IJSproperty)
      var value: string;
      begin
         value := LowerCase(Prop.AsString);
         if ((Length(value) = 7) and (copy(value, 1, 1) = '#')) then
         begin
            try
               Form1.Color := RGB(
                  StrToInt('$' + Copy(value, 2, 2)),
                  StrToInt('$' + Copy(value, 4, 2)),
                  StrToInt('$' + Copy(value, 6, 2))
               );
            except
            end;
         end;
      end));
   ...

Now, let’s see how to achieve this in .Net (C#):

// Creates the remote object
ro = new JSObject("ro");

// Property definition
ro.Properties.Add("backgroundColor")
   .OnGet(new JSBinding(
      // This anonymous procedure do the actual get
      delegate(IJSObject Parent, IJSProperty Prop)
      {
         Prop.AsString = "#"
            + this.BackColor.R.ToString("X2")
            + this.BackColor.G.ToString("X2")
            + this.BackColor.B.ToString("X2");
      }))
   .OnSet(new JSBinding(
      // This anonymous procedure do the actual set
      delegate(IJSObject Parent, IJSProperty Prop)
      {
         string value = Prop.AsString.ToLower();
         Regex reColor = new Regex(@"^#([0-9,a-f]{6})$");
         Match match = reColor.Match(value);
         if (match.Success)
         {
            string color = match.Groups[1].Value;
            this.BackColor = Color.FromArgb(
               int.Parse(color.Substring(0, 2), NumberStyles.AllowHexSpecifier),
               int.Parse(color.Substring(2, 2), NumberStyles.AllowHexSpecifier),
               int.Parse(color.Substring(4, 2), NumberStyles.AllowHexSpecifier)
            );
         }
      }));

To change the background color of the application to red, we just need to assign the property value in Javascript:

ro.backgroundColor = “#FF0000”;

This is the end of our presentation about predefined events and jsRO property setters and getters. In coming installments we will analyze how to work with remote methods and how to define custom events to jsRO object.

 

Leave a Reply

Your email address will not be published. Required fields are marked *