You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Use case: We want to change the state on a sub component
This is currently supported by using view binding e.g.
<client-editor client="{client}" />
Use case: We want to send a message to a child component
Binding works well and it is easy to understand, but there are many situation where we have nothing to pass to the subcomponent. For example we just want to tell our sub-compontent to do something e.g. refresh.
DOM methods
One possible way to do this is attaching methods to the sub-component DOM.
In the sub-component:
// when the component is inserted// we attache a method to its DOM element
events: {inserted: function($ele){varcomp=this;$ele.get(0).refresh=function(args){// ... do something with comp}}}
In the parent:
// when we want to send a message to the child component// we find its element and then call the attached method
events: {'._btn_refresh click': function(){var$comp=$('clients-chooser',this.element);$comp.get(0).refresh(args);}}
Also, at the moment it is possible to get a reference to the scope on a component e.g.
$('child-component').scope();
What if we could get a reference to the component object and just call a method on that?
$('child-component').component().refresh(arg);
This would me totally unecessary the need to attach methods to the DOM.
Use case: We want to broadcast a message to all children
Calling a method on a child components is nice we have exactly one sub component we want to target. But what if there are many or they are nested? One possible way is to be able to broadcast an event to all sub elements.
Use case: We want to send a message back to the parent
Again, there are many times when we don't have a model to bind, we just want to get a result back from the sub-component.
Triggering DOM events
This is a well understood way of doing things. e.g.
In children component:
events: {'a click': function($el,event){varval=$el.html();// we simply trigger a DOM event with the value we wantthis.element.trigger('onSelected',val);returnfalse;}}
In parent component:
events: {'clients-list onSelected': function(ele,event,val){// we receive the event using a normal listener// and do something with itthis.scope.attr('choosen',val);}}
It is easy to introduce bugs if we change the name of the events in one place and not in the other. Is it possible to use constants?
Events bubble all the way up, so potentially being catched by more things that what we want. We have to be careful with the naming of events or stop propagation.
Using a callback
A very well understood pattern in JS is to pass callbacks to objects, broadly used in jquery and jquery plugins. It would be nice to support something like this in can component.
At the moment this doesn't work because can cannot distinguish what is the intention here, e.g. to pass a callback or resolve the function.
A possible solution would be to introduce a stache convention for this:
<clients-list on-selected="{*onChosen}" />
Using can-event
Another possible way is to use can-event at the moment to replicate the callback approach.
<clients-list can-selected="onChosen" />
This looks a lot like the callback example above but note the can- prefix.
In the child component:
events: {'a click': function($ele,event){varval=$ele.html();// ATM crafting an event object is necessary$(this.element).trigger({type: 'selected',val: val});// BUT it would be nice to simply do this:$(this.element).trigger('selected',val);}}
In the parent component:
scope: {chosen: null,onChosen: function(context,elm,event){// ATM we need to extra the argument from the event objectthis.attr('chosen',event.val);}}// BUT it would be nice to simply do this:
scope: {chosen: null,onChosen: function(context,elm,event,val){this.attr('chosen',val);}}