Declaratively invoking a javascript function in Atlas

Posted at Mon, 05 Dec 2005 21:50:33 GMT by Wilco Bauwer

Someone asked me today how one could use the InvokeMethodAction to declaratively invoke a (global) javascript function. It appears it's as easy as this:

ASP.NET:
1 
2 
3 
4 
5 
6 
7 
8 
9 
10 
11 
12 
13 

<script language="javascript" type="text/javascript">
  function test() {
    // code here.
  }
</script>

<atlas:Label runat="server" Text="hello">
    <Behaviors>
        <atlas:ClickBehavior>
            <Click Handler="test" />
        </atlas:ClickBehavior>
    </Behaviors>
</atlas:Label>

Previously, this post was about a workaround which assumed this couldn't be done declaratively. Thanks to Bertrand Le Roy for pointing out that Atlas already makes it trivial to do this. While I'm dumbass for not looking properly in the first case, my excuse is that I'd expect to have a 'Click' attribute on objects instead/as well.

Hi Wilco,

Good stuff, keep it coming!

Just a small remark that might be usefull for the people that use this control...

When you want to pass on parameters you need to set the bindings as follows:

<Actions>
<atlas:InvokeMethodAction Target="Window1" Method="TestMethod">
<Bindings>
<atlas:Binding DataContext="MyControl" DataPath="text" Property="parameters" PropertyKey="Key" />
</Bindings>
</atlas:InvokeMethodAction>
</Actions>

Somehow when I ommit the Property And PropertyKey attributes it won't work. Not sure why as they don't seem to be usefull in this scenario.
Hi Wilco,

I hate to say that, but I'm not sure this is very useful: all event handlers can have actions as well as a handler. In your example, instead of writing this:
<ClickBehavior>
<Click>
<Actions>
<InvokeMethodAction Target="myWindow" Method="test" />
</Actions>
</Click>
</ClickBehavior>

I think you can write this:
<ClickBehavior click="test"/>

It's more concise and you don't need an additional component.
Did I miss something?
Oops! As you're using the server controls, from the top of my head, it's probably something like <Click handler="test"/>. I'll check tomorrow.
Well, if we had documentation, this wouldn't happen ;) And actually I think currently the best documentation for Atlas is your class browser...
Well, just to get back to the question at hand, you don't write JavaScript the same way you write C# (it's interpreted, mono-thread, objects don't have the same price and so on). This is reflected in the way Atlas in architectured. For example, instead of putting as much stuff as possible on the base Control class, we're going to limit the number of members to the minimum. Instead, we're going to add atoms of functionality like the click behavior, which enables you to add aspect-like things to objects as needed. It makes it lighter, and ultimately more extensible, even if the syntax tends to be a little more verbose.
I kind of meant that I expected the handler to be on the object such as the ClickBehavior. Instead of:

ASP.NET:
1 
2 
3 

<atlas:ClickBehavior>
  <Click Handler="myHandler" />
</atlas:ClickBehavior>



I would prefer something like:

ASP.NET:
1 

<atlas:ClickBehavior Click="myHandler" />



It's just a subtle difference, but I think it may make a difference, since in 8/10 cases a nested element is usually a container of something on which you rarely actually set attributes.
Yes, and that's the syntax of the client markup. The server markup tends to be more verbose, but then again we're rethinking that part entirely.
hi
nice code.
it's posible pass parameters to the jscript function.


saludos
This is very useful. the next step would be to call a JS function that requires parameters:

function test(var1, var2) {
// code here.
}

I tried without success
<Actions>
<atlas:InvokeMethodAction Method="SetFilters" >
<Bindings>
<atlas:Binding DataPath="Id" Property="text" PropertyKey="myKey" />
</Bindings>
</atlas:InvokeMethodAction>
</Actions>

Do you have any suggestions? Thanks

Just like the pattern in .NET, Atlas will pass a sender and event args object to the handler. You can use the sender to get to the data context. This could look like:

ASP.NET:
1 
2 
3 
4 
5 
6 
7 
8 
9 
10 
11 
12 
13 

<script language="javascript" type="text/javascript">
  functoin MyHandler(sender, args) {
    var dc = sender.get_dataContext();
    var descr = dc.getProperty("Description");
    alert(descr);
  }
</script>

[...]

<atlas:Button ...>
  <Click Handler="MyHandler" />
</atlas:Button>



In this example, the button could for example be a button defined inside a ListView.

HTH.
Nice! it works like a charm. Thanks for the tip!

-Riccardo
Maybe I'm just being dense, but what the heck is the advantage over this verbose syntax instead of directly adding an onclick to the control? C'mon folks, we're making things harder now, not easier...

Sure there will be cases where the declarative syntax might make sense such as binding call parameters, but even then this seems like overkill. You still have to decide what gets bound to what anyway, and whether you do this mapping using explicit JScript references or some funky markup declaration you're still mapping one way or the other. If I have a choice there the native code is a better choice - more lightweigth, more portable and most of all more logical.


One of the reasons why it was like this is that Atlas provides controls/behaviors on top of (D)HTML to make things such as client-side bindings possible. One of the things that these higher-level controls provide is events that wrap the underlying events to make things such as actions possible.

To avoid wrapping several events in each control (potentially leading to larger JS files), I believe the Atlas team decided to provide a few behaviors instead, which people can then use on any control.

The code in this post is no longer valid in the latest CTP's though. There no longer seems to be a separation of control sets (ASP.NET vs. Atlas controls), but instead Atlas provides an extension to existing ASP.NET controls through Extenders.
Hello Wilco,

what about using the new declarative XML script to generate the button click events?

How to turn:

<atlas:Label runat="server" Text="hello">
<Behaviors>
<atlas:ClickBehavior>
<Click Handler="test" />
</atlas:ClickBehavior>
</Behaviors>
</atlas:Label>

into the <xml script> tags?

<label>
<behavoours>
<clickBehavour>
<click Hander="test">
</clickBehavour>
</behavuoirs>
</label>

Doesnt seem to be making the call
Your message will be encoded/formatted when it is displayed. If you want to post code, please put the code inside [code=X][/code] tags, where X is the language of your code (C#, ASPX, SQL, etc).
Name:
Email:
(will be encoded using JavaScript to keep it functional and prevent it from being picked up by spammers)
Url:
 
Message:
3 + 3 =