Skip to main content
Version: 8.1

Component Message Handlers

Inductive University

Message Handlers

Watch the video

In Perspective, Component Message Handlers are the preferred way to pass parameters between components or Views. Doing this involves the system.perspective.sendMessage function. There are typically two steps involved:

  1. Creating a message handler on the component that will listen for a particular call.
  2. Create a script that will call the message handler.

This page will demonstrate how to prepare both steps. The goal of this example is to create a script that will cause a button to change the text property of a Label.

Object Traversal​

Inductive University

Component Paths

Watch the video

When writing a component based script, Object Traversal should be avoided where possible. Object Traversal is the process of declaring hard-coded component paths in a script similar to how the Vision module uses component paths in scripting. While component paths exists in Perspective, they are brittle: changes to the hierarchy in the view (such as placing a component into a new container), or changing a component name will invalidate any paths defined before the change, since the component's relative location has changed.

Consider the following:

Pseudocode - Example Path
self.getSibling('Text Field').props.text

The path described above only works if there is component named "Text Field" in the same container as the component that is running this script. If the Text Field component is renamed at any point, this reference to the component will fail. Additionally, if the Text Field is placed in a different container, then the getSibling() call will no longer work. Components in other containers (in the same view) are available, but are not siblings.

Additionally, Object Traversal can't be used to reference a property in a separate view: i.e., a script in View A cannot reference something in View B.

We strongly suggest you utilize message handlers when a script is trying to interact with a component in another View.

Message Types​

When sending a message, the Message Type field represents which Message Handler should respond. If a script sends a message with a type of "foo", then any handler listening for a Type of "foo" will execute. This means multiple components in the same window can all have Message Handlers with the same Type: e.g., if a view has a "reset" button to clear out multiple input components, then each input component can simply have a "reset" message type that clears the field, allowing a single message to trigger multiple handlers. Alternatively, if only a single handler should execute when sending the message, simply give that one handler a unique Type.

Message Handler Scope​

Message Handlers can be limited in scope, meaning the range of the sent message (or range of the listener) can be confined to a particular scope. The available scopes are:

ScopeDefinition
ViewMessages can only be heard by listeners within the same View that are listening for view-scoped broadcasts.
PageMessages can only be heard by any listeners within the same Page that are listening for page-scoped broadcasts. This includes listeners both within the same View and those in other Views contained within the same page (including Docked Views and Popup Views).
SessionMessages will be heard by any listeners in any open tabs in your workspace that are listening for session-scoped messages.

For example, you can send a message that is scoped to just the View where the message originated, meaning only listeners in the same View will be able to respond. This is useful if you sent a message from a popup view, and didn't want any other views to respond.

There are two ways to limit the scope of a message:

  1. The system.perspective.sendMessage function contains a scope parameter that will restrict the range on the message being sent.
  2. The Message Handlers have a Listen Scopes setting that can filter out messages from certain scopes.

Message Handler Example​

Step 1 - Prepare Perspective Workspace​

  1. Open the Designer.

  2. Switch over to the Perspective Workspace by clicking on Perspective in the Project Browser.

  3. Right-click on the Views folder and select New View.

  4. Give the new View a name and click the Create View button. The name of the view will not matter for this example.

  5. Place a Button and a Label component on the View.

Step 2 - Create A Message Handler​

Message Handlers are effectively user-created scripting events. A user can define a Message Handler that listens for a particular message. The idea being that some other component will broadcast a message, and if the type of the message matches what the Message Handler is listening for, the Message Handler will execute a script.

Message Handlers are useful because they can respond to messages from multiple components: if something sends a message with the correct type, then the Message Handler will execute. Additionally, message can be sent across separate views, pages, or throughout the entire session.

In our example, we want the Label's text property to change when something else in the view happens (in our case, our button is pressed), so it would make sense to configure a Message Handler (listener) on the Label. This way, if we relocate the Label component in the view, the script will still work.

  1. Right-click on the Label, and select Configure Scripts.

  2. The Script Configuration window appears. Make sure the title bar on the window states that it's the Label component.

  3. On the left side of the Script Configuration window, you will see a tree. Double-click on the Add handler... item.

  4. A new handler named "type-name-here" will appear. Under Message Type type my-handler. Note that we're using all lowercase characters: message handlers are case-sensitive. The Message Type is effectively the name of the message handler. When sending a message, we will specify this message handler's type, which will cause it to respond by executing the script.

  5. In our example, let's change the text on the Label to "Hello!". Under the script area, type the following script:

    Python - Set the Text
    self.props.text = 'Hello!'
  6. This example is fairly limited to this one view. Thus, let's limit the scope so that it will only respond to messages from the same view the Label is on. Under the Listen Scopes, leave Page as the only selected scope.

  7. Click the OK button. We just created a Message Handler. In the next step, we'll create a script that will call the Message Handler.

Step 3 - Send A Message​

In this step, we place a script on the Button that will call our Message Handler.

  1. Right-click on the Button, and select Configure Events.... The Event Configuration window appears.

  2. We want our script to trigger when the button is pressed. On the left side of the window, in the Mouse Events folder, select onClick.

  3. The Organize Actions list will appear. Press the Add icon. A popup list will appear.

  4. Select the Script action.

  5. Add the following code:

    Python - Sending a Message
    messageType = 'my-handler'
    system.perspective.sendMessage(messageType)

    Make sure the script lines are indented one time.

  6. Click OK to apply the script.

The example is now running. From the Designer, enable Preview mode, and then click on the Button component. The text on the label should update.

note

In this simple example, the major issue you may run into is the Message Type. Recall from #4 in Step 1 of the example, that Message Type is case-sensitive, so make sure the script on the Button is correctly referencing the message type, and try again.

Passing Parameters Example​

Let's make the previous example more complicated and pass some values with the message. The example above can be modified to determine the timestamp. When passing parameters in a script, the most direct approach is to include any parameters along with the message. Message Handlers have a built-in argument called a payload, which is used to transfer values to the handler. The payload is simply a Python Dictionary, so please see the Dictionaries page for more information.

Alternatively, we could create a session property to hold the value, and have the label reference the session property. However this would require that we either create a new property to hold the value or overwrite the value of another property. Thus, our next example will demonstrate how to utilize the payload.

Avoid Storing Values in Tags

Since Tag values are shared by all Perspective sessions, you may not want to write the parameters in Tags. Doing so would result in each session instance potentially trying to overwrite the same value.

Step 1 - Update the Button Script Action​

  1. Right-click on the Button component and select Configure events....

  2. Replace the code with the following:

    Python - Check the Time, Send a Message
    messageType = 'my-handler'

    # Look up the current time.
    currentTime = system.date.format(system.date.now(), 'HH:mm:ss')

    # Create a payload to be passed with the message
    payload = {'time':currentTime}

    # Send the message, pass the payload, limit the scope to the view
    system.perspective.sendMessage(messageType, payload, scope = 'view' )
  3. Make sure the code is indented one time.

    note

    On line 8, we're creating a dictionary, creating a key called "time", and storing the current time with the "time" key. When our handler receives the payload, it can retrieve the value we passed by referencing the "time" key.

  4. Once finished, click the OK button.

Step 2 - Update the Message Handler​

Now that we're including a payload with the message, we need to modify our handler so that it will extract the time from the payload.

  1. Right-click on the Label component, and select Configure scripts....

  2. Replace the original code with the following:

    # Access the time by referencing the 'time' key
    self.props.text = payload['time']
  3. Click OK.

  4. To test it, enable Preview mode, and click the Button component. You will see the current time populate in the Label.