I just want to bring two examples for binding ZTL events to BIAL script, listed in the blog from Reiner:

What’s Coming in Design Studio 1.4 SDK

and discussed in the threads:

DS 1.4 SDK: binding events to DS script

Design Studio 1.4 SDK – What is the correct approach for binding events to script methods for UI5-based components?

The examples are commited in the community repository in prototypes area, under:

app.PNG

The example is based on the question from Mustafa, how to automatically place the title from application name.

Basics

The events are send to the server, but not directly at the place where the call is located – and by this, you cannot expect that the next line in Java Script is already processed with the new values. The normal process sequence is still applied, the init method in the component and the update method in the component will be executed, then – if the event is directly placed in the update method – the event will be send to the server and again the update method will be executed. This can basically lead to endless loop, if the called method in ZTL will always change the component properties. if not, the loop will be broken by the current implementation of delta handling in design studio SDK.

The automatic bound events to private methods are positioned for user interaction of the component which does not require special code done by the developer (as the code is not dependent on other components in the application). For pushing some information to the component the implicit event “onBeforeRender” should be used.

Example 1.

Use of the onBeforeRender event linked to a method.

extension of contribution.xml:


<property
  id="onBeforeRender"
  title="Set Application Name"
  type="ScriptText"
    visible="false"/>
<property
  id="appName"
  title="Application Name"
  type="String"
  visible="false"/>
and...
<defaultValue property="onBeforeRender">this.private_beforeRender();</defaultValue>


extension of contribution.ztl:


// @Visibility(private)
  void private_beforeRender() {*
    // APPLICATION.createInfoMessage("Name: " + APPLICATION.getInfo().name);
      this.appName = "OnBeforeRender: " + APPLICATION.getInfo().name;
  *}


extension in java script file:


  afterDesignStudioUpdate: function() {
    // Set the logo text to the appName property filled by the onSetAppName event script
    this.setLogoText(this.getAppName());
  }


Example 2.

Use of implicit event which is triggered after initial rendering of the component.

extension of contribution.xml:


  <property
    id="onSetAppName"
    title="Set Application Name"
    type="ScriptText"
    visible="false"/>
  <property
    id="appName"
    title="Application Name"
    type="String"
    visible="false"/>
and...
<defaultValue property="onSetAppName">this.private_setAppInfoName();</defaultValue>


extension of contribution.ztl:


/* Sets the value of the invisible property appName to the application name */
  // @Visibility(private)
  void private_setAppInfoName() {*
  // APPLICATION.createInfoMessage("Name: " + APPLICATION.getInfo().name);
     this.appName = "Event: " + APPLICATION.getInfo().name;
  *}


extension in java script file:


afterDesignStudioUpdate: function() {
  // Set the logo text to the appName property filled by the onSetAppName event script
  this.setLogoText(this.getAppName());
  // Raise the onSetAppName event to execute the script for getting the application name
  this.fireDesignStudioEvent("onSetAppName");
}


Pros & Cons.

For this use case – fill in some information automatically on first rendering, example 1 is better, because:

  • it is triggered on the server “before render”
  • does not require additional roundtrip

Example 2 is positioned to an user action event which does not need to be coded by the application designer, therefore for this scenario it is not the best way, because:

  • it triggers additional request after first rendering which causes second rendering of the component.

Question 1

is there a difference in the sequence of the calls like below?


  // Set the logo text to the appName property filled by the onSetAppName event script
  this.setLogoText(this.getAppName());
  // Raise the onSetAppName event to execute the script for getting the application name
  this.fireDesignStudioEvent("onSetAppName");

VS.


  // Raise the onSetAppName event to execute the script for getting the application name
  this.fireDesignStudioEvent("onSetAppName");
  // Set the logo text to the appName property filled by the onSetAppName event script
  this.setLogoText(this.getAppName());

     Answer:

          No, there is no difference.

     Reason:

          The fireDesignStudioEvent call is NOT executing immediately, as there is no option to come back into the next line. The event is collected and executed after all component rendering is processed. Then, the normal dispatching is taking place – and leads again to the call into the function afterDesignStudioUpdate. Of course, this leads again to the trigger of the event – and in case the specific event implementation will return different value, there will be an endless loop. In case of the same value, the loop is stopped by the delta handling of SDK components (same values will be not send again..)

Question 2

why the events are not executed in design time?

     Answer:

          Designer is WYSIWYG, but not 100% – the onStartup scripts will be not executed as well. And looks like the events are also removed from the execution. The WYSIWYG is more linked to the layout and data display, but the initial interactivity is not included.

     Reason:

          The initial eventing in designer would lead to huge complexity, as the events can change the properties of the components – and then it would be a question which are now valid during the editing of the template – those saved in template or those set by the scripts.

Learning

  • the triggering of implicit events cannot be made in “initDesignStudio” method, those can be made ideally on user action, but implicitly also in “afterDesignStudioUpdate”
  • there is a bug in DS 1.4 SP0 (correction will be delivered in SP1) and the marker “@Visibility(private)” is not working at all (the method is not visible)
  • example 2 with the event would cause an endless loop, which is not occurring only because in this case the value is not changing and DS 1.4 supports delta rendering (is checking if the values have changed)

Code Example

Application

you just need to create new application and drag&drop one of the components.

Have fun with this examples.

To report this post you need to login first.

8 Comments

You must be Logged on to comment or reply to a post.

  1. Vincent Dechandon

    Anyhow, I was just wonderng what was the point of doing this.fireDesignStudioEvent(“onSetAppName”);  in the example 2 ? Because the this.getAppName() called just before logically already owns the application name.


    Br,

    Vincent

    (0) 
  2. Mustafa Bensan

    Hi Karol,

    Thanks for this write-up with examples.  It makes the functionality much clearer now.  I have a couple of follow-up questions though.

    1)  Similar to Vincent’s question above, although Example 2 does indeed work as documented, I am wondering why the this.setLogoText(this.getAppName()) statement is executed before this.fireDesignStudioEvent(“onSetAppName”) instead of after?  I ask this because the appName property doesn’t get populated until the private_setAppInfoName() ZTL method is called, which only occurs when the script bound to the onSetAppName event is executed via fireDesignStudioEvent.  Since the solution works as coded, I am assuming that somehow the afterDesignStudioUpdate() function is called twice in succession and therefore this.setLogoText(this.getAppName() actually has a value the second time around.

    As a test, I tried the code in the following sequence that I would have expected and found that it also works:

    1. afterDesignStudioUpdate: function() {
    2. // Raise the onSetAppName event to execute the script for getting the application name  
    3.   this.fireDesignStudioEvent(“onSetAppName”); 

    4.   // Set the logo text to the appName property filled by the onSetAppName event script  
    5.   this.setLogoText(this.getAppName()); 

    Can you help me understand the appropriate sequence of the calls?

    2)  The example has confirmed a suspicion that event bound script methods are unfortunately not executed at design-time in the Design Studio canvas, so we have the following result with our example case:

    AppName does not appear in the Application Header on the Design Studio canvas:

    ApplicatioHeaderDesignStudio.png

    But when the Design Studio application is executed the AppName does appear in the browser:

    ApplicationHeaderBrowser.png

    Is there a workaround for this?  I think there are two very important reasons why it would be beneficial to be able to execute ZTL methods in design mode:

    1)  The Design Studio canvas is intended to be a WYSIWYG representation of the appearance of the application, so to be consistent with this, any information obtained from the BIAL API via a ZTL method for inclusion in the component display should also be visible in design mode on the canvas.  This also applies if the data source Initial View could be manipulated via a ZTL method call from the Additional Properties Sheet (see point 2 below for an additional related use case);

    2)  More importantly though, there are cases where accessing the BIAL API from the Additional Properties Sheet via a callRuntimeHandler function to execute an event bound script method would be very useful, to obtain information that is not otherwise available.  A good example of this is to display a list of all the dimensions included in the free axis of a data source as shown below (to allow configuration of dynamic filtering and display of dimensions by the component for example):

    InitialView.png

    In this scenario, the free axis dimensions are not available in the MetaData or Data JSON of the data source (only the ones in the column and row axes are), so the only way to obtain this information is by calling the BIAL API getDimensions(Axis.FREE).  This is just one example but I think there would be a number of other uses cases for being able to access the BIAL API from the Additional Properties Sheet.

    I’d very much appreciate your thoughts and suggestions on the above.

    Regards,

    Mustafa.

    (0) 
    1. Vincent Dechandon

      I think fireDesignStudioEvent call is triggering again all getter/setter from the component, thats why it is working. But it’s an infinite loop as   Karol said

      (0) 
    2. Karol Kalisz Post author

      Hi Mustafa,

      for the first two points, I have extended the blog with answers. Basically, the event call is not “synchronous” – it is just waiting on all dispatcher work and then will be send to server.

      for the APS topics – isn’t is possible to call own method of the component currently? Probably this could be done as workaround via update on some dummy property which would just execute some script instead of property update.

      Karol

      (0) 
      1. Mustafa Bensan

        Hi Karol,

        Thanks for updating this blog with further details.  I’m not entirely clear on the APS workaround.  What do you mean by calling the component’s own method?  The APS has it’s own getter/setter functions.  Are you suggesting that a BIAL script can be executed inside a setter function?

        Mustafa.

        (0) 
        1. Karol Kalisz Post author

          Hi Mustafa,

          for the APS, I just checked the documentation – indeed there is no direct access from APS to ZTL functions.


          I thought that the “set<Property>()” function can be called, but not – there is only the event “firePropertiesChanged” which is immediately replacing the value, therefore the ZTL access from APS would be an extension requirement and we would need opinion from Reiner on this topic.

          Karol

          (0) 
          1. Mustafa Bensan

            Hi Karol,

            Thanks for the confirmation.  It would be great if such an APS ZTL access extension could be considered, at least for BIAL APIs that return information that would not otherwise be available to the APS, such as that provided by getDimensions(Axis.FREE) just as one example.

            Regards,

            Mustafa.

            (0) 

Leave a Reply