Calling $(event) from within a composite component

With a plain html button I can use the $(click)='methodToCall' to wire up a method to the click event.

Let’s say that I create a custom button component. How would I wire up the click event in the contained code? The following does not seem to work:

button.stache:
<button type=“button” class=“btn {type}” $(click)="{click}">
{{i18n ‘{text}’}}

button.js:

Vision.Components.Button = can.Component.extend({
    tag: 'vision-button',
    template: can.view('components/button.stache')
});

Using the <vision-button click='myMethod' text='myText' /> does not seem to get the job done. In fact, the i18n helper is also not called.

Where am I going wrong?

It’s ($click)="methodToCall"

I’m a bit confused by the example. {{i18n '{text}'}} doesn’t seem right to me either.

Anyway you can create a JSBin?

Ok, I fixed the ($event) thingy. I’m really not concentrating :slightly_smiling:

Anyhow, here is a jsfiddle: http://jsfiddle.net/EbenRoux/qYdwR/2585/

I think I’ve figured it out, and this time really fixed the $(click) on my new fiddle:

http://jsfiddle.net/EbenRoux/qYdwR/2587/

Is this the way to go or is there some simpler mechanism?

If I understand what you are trying to do here, it’s as simple as passing the method to the child component and using it in the child component’s template.

parent.stache:

<button-component {click-method}="@callMe" text="click me"></button-component>

button.stache:

<a href="javascript://" ($click)="clickMethod()">{{text}}</a>

New to 2.3, @ allows you to pass the function reference without executing it. Before this, the traditional approach would be to pass an object with the method like this:

<button-component {button-options}="buttonOptions" text="click me"></button-component>
...
<a href="javascript://" ($click)="buttonOptions.clickMethod()">{{text}}</a>

hi eben,

i looked into your jsfiddle and i am a little confused :wink:

i made a jsbin example with your code and cleaned up some code.

first thing catches my eyes is:
your components attributes have to kebab-case. so click-method become clickMethod in the stache template

second:
you can dynamic bind on your click-method by using ($click)="{{clickMethod}}"

third:
you can specify your click method in the viewModel of our component. is you have the same the same method on the Map you commit to the main-template you can use click-method="../callMe"to use the parent scope.

fourth:
i used simpleHelper for stache, so text is passed as the value instead of a compute

hope that helps you

Brilliant!

Thanks for the help. I was about to give up on CanJS :slight_smile:

In general, you can often avoid dynamic binding like this. You can have:

($click)="method()"

And then a method that calls clickMethod like:

method: function(){
  this.attr("clickMethod")();
}

This is especially useful if you want to call one function or another depending on some criteria.

Quite elegant. Along the lines of my contrived solution :blush:

Feeling excited about this again!

pYr0x’s example of ($click)="{{clickMethod}}" works a charm but the following fails:

method: function(){
  this.attr("clickMethod")();
}

Seems as though the actual click method that is part of the ‘parent’ view model is not available in the component’s view model. Perhaps I’d need to explicitly add the parent view model as I did in my contrived example; else just bind directly.

I’ll see if I can create a jsfiddle tomorrow.

Seems as though the actual click method that is part of the ‘parent’ view model is not available in the component’s view model.

Yeah, I was assuming it was passed to the component.