Click handler arguments suddenly undefiend

I need to update an app I made last summer, but when I loaded the app into the latest version of Fuse I get errors because click handler arguments don´t contain the data that it used to when I wrote the app. (There might be other errors also, but this is as far as I have gotten)

I have a menu with MenuItem components. Each menu item has a variable text that contains the name of the button. This variable is also exported.

Pseudocode example:

MenuItem component

<Rectangle ux:Class="MenuItem">
  <JavaScript>
    var Observable = require("FuseJS/Observable");

    var text = this.Text.inner();

    module.exports = {
      text: text
    }
  </JavaScript>

  <MyTextComponent
    Value="{Property Text}"
  >
  </MyTextComponent>
</Rectangle>

Implementation with click handler in main file

<JavaScript>
  function menuButtonClicked(args) {
    console.log("args = " + JSON.stringify(args));
    console.log("text = " + args.data.text.value);
  }
</JavaScript>

<ClientPanel>
  <MenuItem Text="Menu item title"  Clicked="{menuButtonClicked}">
    <Clicked>
      <NavigationToggle Target="sidebar />
    </Clicked>
  </MenuItem>
</ClientPanel>

In my code the console log for args above will be {"node":{"external_object":{}},"x":89.5,"y":130,"index":0,"localX":89.28315734863281,"localY":59.617332458496094}

Args.data.text.value therefore becomes undefined.

Since I want to use the text value this is a bit of a problem. When I wrote the code args.data.text.value would contain the value of the text variable defined in MenuItem.

I have googled a bit to try to find out if the way arguments for click handlers are handled have changed, but I haven´t found anything.

Anyone see the problem in my code?

Example project with error:

Just ran it and got this in logs:

[Viewport]: args = {"node":{"external_object":{}},"data":{"text":{"_origin":-6,"_subscribers":[{"version":2,"active":true}],"_isProxy":true,"_values":["Demo"],"_subscriptionWatchers":[{"watcherId":2}],"_beganSubscriptions":true},"trallala":"trallala"},"x":197.5,"y":18,"index":0,"localX":197.5,"localY":18}
[Viewport]: testvar = Demo

Does that mean it runs just fine for me?

Did you run uno clean in the project root folder after upgrading Fuse?

Very weird…

I have run ´uno clean´ on the original project. The demo project was made from scratch, so running uno clean shouldn’t be necessary?

I now tried the demo project on PC (it was originally developed on Mac) and get the same error. Before running it I updated Fuse from an ancient version to the latest version.

I even tried recreating the project on PC in case there were som kind of weird file formatting error.

Still on PC:

  • Uninstalled Fuse (latest version)
  • Installed v1.4.0. (This is the last version I remember having on the Mac before upgrading to 1.7.x.)
  • Demo project works
  • Upgraded to 1.7.3
  • Demo project fails

Did some more tests: Demo project works on 1.6.0 and 1.6.1, fails on 1.7.0

I forgot to run uno clean between installing different versions, though…

It looks like this might be a regression after all. I’ve now logged a ticket and you can follow the status there.

It turns out this was a deliberate change to fix a number of underlying issues with data contexts. While your particular project currently doesn’t work and will need some refactoring, it’s all for the better.

The problem is that you’re relying on unfortunate, unplanned-for behaviour that shouldn’t be there in the first place. It’s now gone.

So, as explained in the linked ticket, you have at least two ways to solve this.

One, by using explicit data contexts, like so:

<App>

  <JavaScript>
    function menuButtonClicked(args) {
      console.log("args = " + JSON.stringify(args));
      console.log("testvar = " + args.data.label);
    }

    module.exports = {
      menuButtonClicked: menuButtonClicked,
      menuButton: {label: "Demo"}
    }
  </JavaScript>
  
  <ClientPanel>
    <With Data="{menuButton}">
      <MenuItem Label="{label}" Clicked="{menuButtonClicked}">
      </MenuItem>
    </With>
  </ClientPanel>

  <Rectangle ux:Class="MenuItem" Row="0" Column="0" Color="#030303">
    <string ux:Property="Label"/>

    <JavaScript>
      var Observable = require("FuseJS/Observable");
      var text = this.Label.map(x => 'Label: ' + x);
      module.exports = {
        text: text
      }
    </JavaScript>

    <StackPanel>
      <Text
        Background="#f00"
        Color="#fff"
        FontSize="22"
        Alignment="Center"
        Margin="0,0,0,100"
        Value="{text}">
      </Text>
    </StackPanel>
  </Rectangle>

</App>

Here, the menuButton variable itself is available in the data context the callback lives in, and we pass it to the MenuButton by using With.

If this for any reason doesn’t work in your case, another option is to use UserEvents. Those support passing arguments as well.

Thank you for the info and example, Uldis!

I have now refactored the code, hopefully finding all places creating issues. :slight_smile: