How to create a bubbling custom event in Flex 4?
To create and expose a custom event in MXML, you need to declare it at the component that will dispatch the event with this line:
<fx:Metadata>
[Event(name="select", type="my.engine.events.SelectionEvent")]
</fx:Metadata>
This allows you to:
<my:CustomComponent select="doSomething()"/>
However, how do you make this bubble upwards. I want to do this
<s:DataGroup select="doSomethingForAll();">
<s:itemRenderer>
<fx:Component>
<my:CustomComponent/>
</fx:Component>
</s:itemRenderer>
</s:DataGroup/>
Thanks!
Your Custom event must extend Event. On constructor you'll find name:string, bubbling:boolean, and cacellable:boolean as arguments.
Set the bubbling parameter to true. In your example, the metadata tag must be in your DataGroup tag.
One possible solution but not exactly what i was looking for is to add this line of code at the DataGroup level.
this.addEventListener(SelectionEvent.SELECTED, onSelect);
This will ensure all events fired by CustomComponent is cought.
You can either extend s:DataGroup container with specified custom metatag data information built-in into the extended class or you can either call "doSomethingForAll()" method from itemRenderer's "select" event handler, see code below:
<s:DataGroup
dataProvider="{instructions}"
width="100%">
<s:itemRenderer>
<fx:Component>
<my:CustomComponent
select="rendererSelect()">
<fx:Script>
<![CDATA[
protected function rendererSelect():void
{
outerDocument.doSomethingForAll();
}
]]>
</fx:Script>
</my:CustomComponent>
</fx:Component>
</s:itemRenderer>
</s:DataGroup>
Catch the dataGroups select event and then dispatch a doSomethingForAll()
Make sure the doSomethingForAll event has it's bubbling property set to true.
Then any event listeners listening for doSomethingForAll above it in the display list will get called.
Related
How can I add multiple event listeners to an event in UI5?
We have a master list with a dropdown that is correctly firing a select event on its controller. Sub controllers also need to be informed that this dropdown has changed in order to reload model data.
onAllRolesChange: function(oEvent) {
var key = oEvent.getParameter("selectedItem").getProperty("text");
if (this.ScreenId != null) {
this.loadScreenByRole(key);
// I could invoke the controllers directly, but that seems wrong
// controller2.update();
// controller3.update();
}
},
I assume what I should be aiming for is to call some sort of registerForEvent() method in each of the controllers, but I don't see anything like that in the SDK. fireEvent() and attachEvent() exist, but the examples I've seen appear to be for creating custom controls, or responding to browser events that SAP hasn't implemented.
As of UI5 1.65, multiple event handlers can be assigned when creating ManagedObjects / Controls:
(...) ManagedObjects now accept an array of multiple event listeners for an event. To
distinguish this use case from the already supported array with [data, listener, this], an array with multiple listeners must use nested array notation for each listener as well [in JS]. In XMLViews, multiple listeners have to be separated by a semicolon. (source)
Syntax
In XMLView
<Button press=".myControllerMethod; .mySubController.thatMethod" />
In JS
new Button({
press: [
[ listener1 ], // 1st listener
[ data, listener2, thisArg2 ] // 2nd listener
]
});
Demo
sap.ui.getCore().attachInit(() => sap.ui.require([
"sap/ui/core/mvc/XMLView"
], XMLView => XMLView.create({
definition: `<mvc:View xmlns:mvc="sap.ui.core.mvc"
xmlns="sap.m"
height="100%"
displayBlock="true"
>
<Button text="Press" class="sapUiTinyMargin"
press="alert('1st event handler'); alert('2nd event handler')"
/>
</mvc:View>`,
}).then(view => view.placeAt("content"))));
<script id="sap-ui-bootstrap"
src="https://openui5nightly.hana.ondemand.com/resources/sap-ui-core.js"
data-sap-ui-libs="sap.ui.core, sap.m"
data-sap-ui-async="true"
data-sap-ui-compatVersion="edge"
data-sap-ui-theme="sap_fiori_3"
></script>
<body id="content" class="sapUiBody"></body>
You could use the EventBus to inform about the change, and who ever wants could listen for the change. However, if the other controllers are not yet loaded they won't get the events of course... Maybe you can combine this with promises...
You could also use a global model with 2 way binding and use it for your dropdown. When ever the dropdown changes the change is reflected in the corresponding model. At the same time, in your sub controllers you could create a sap.ui.model.Binding(...) for the same global model + path etc used for your dropdown. Additionally, you would attach a handler for the change event of the Binding... That should work as well. However, this has the same disadvantage like using the EventBus, but maybe thatÄs not an issue for you...
I am trying to trigger an event in the marionette itemview (List.SendQuestion), however, I was unable to register the trigger in the controller (as seen below)
Essentially, after clicking on the 'a.send', a trigger was supposed to happen and the 'send_qn_view' should capture the event and print out the message 'triggered'. But that was not happening.
Can someone advise me what might be going wrong here?
#Dailymuses.module "SidebarModule.List", (List, App, Backbone, Marionette, $, _) ->
List.Controller =
showSidebar: ->
send_qn_view = new List.SendQuestions
collection: Onethingaday.Public.friends
send_qn_view.on "itemview:ask:user", (itemview, question) ->
console.log('triggered') #THIS IS NOT EXECUTED
class List.SendQuestion extends Marionette.ItemView
template: "sidebar/list/templates/send_question"
className: 'qn_askee'
tagName: 'li'
events:
"click a.send" : "sendQuestion"
sendQuestion: (e) ->
e.preventDefault()
debugger #this debugger was triggered
#trigger "ask:user", #model
class List.SendQuestions extends Marionette.CompositeView
template: "sidebar/list/templates/send_questions"
itemView: List.SendQuestion
itemViewContainer: "ul.friends"
Edit: Corrected my answer and updated my fiddle
Sorry about that. Your syntax for event bubbling is correct.
https://github.com/marionettejs/backbone.marionette/blob/master/docs/marionette.collectionview.md#childview-event-bubbling-from-child-views
"itemview:*" event bubbling from child views
When an item view within a collection view triggers an event, that
event will bubble up through the parent collection view with
"itemview:" prepended to the event name.
That is, if a child view triggers "do:something", the parent
collection view will then trigger "itemview:do:something".
Something to note. Marionette supports view triggers. If your callback is just triggering a view event you can remove the event hash and callback and shorten your code to this:
triggers: {
"click a.send": "ask:user"
}
http://lostechies.com/derickbailey/2012/05/15/workflow-in-backbone-apps-triggering-view-events-from-dom-events/
Fiddle:
http://jsfiddle.net/FRHkt/1/
For anyone new coming to this example, with Marionette 2.x, itemview:* for children views have been replaced with childview: triggers in the parent view, and the collection and composite views have also had their parameters changed from itemView and itemViewContainer to childView and childViewContainer
I'm having a hard time understanding the syntax of the .delegate function of jquery. Let's say I have the following:
$(".some_element_class").delegate("a", "click", function(){
alert($(this).html());
});
I know that the a element is the element to which the click event is applied. I know that once we click on that a element, the event click will be triggered and the callback function will be called. But what is the purpose of what comes before the .delegate? In this case, what is the purpose of .some_element_class? How do I read the above including the .some_element_class? Also, in the example above, what does $(this) represent? Does it represent the a element or does it represent .some_element_class?
Please somebody, shed some light on this.
Thank you
This reduces event binding.
This basically sets an event on a tags ONLY within the elements with class .some_element_class without actually binding an event to a tags directly.
http://api.jquery.com/delegate/
http://api.jquery.com/on/
As of jQuery 1.7, .delegate() has been superseded by the .on() method.
For earlier versions, however, it remains the most effective means to
use event delegation. More information on event binding and delegation
is in the .on() method. In general, these are the equivalent templates
for the two methods:
$(elements).delegate(selector, events, data, handler); // jQuery 1.4.3+
$(elements).on(events, selector, data, handler); // jQuery 1.7+
$(".some_element_class").on("a", "click", function(){
alert($(this).html());
});
"...what is the purpose of what comes before the .delegate?"
A delegate is bound to .some_element_class element.
That delegate is triggered for every click that takes place inside .some_element_class
That delegate tests what was clicked, so your handler function will only run if...
the actual element clicked matches the "a" selector, or
any ancestor of the actual element clicked that is a descendant of .some_element_class matches the "a" selector.
<div class="some_element_class"> <!-- delegate handler is here -->
<div>won't trigger your handler</div>
<a>will trigger your handler</a>
<a><span>will trigger</span> your handler</a>
</div>
So you can see that only one handler is bound to the container. It analyzes all clicks inside the container, and if the element clicked (or one of its nested ancestors) matches the selector argument, your function will run.
Because there's just one enclosing handler, it will work for future elements added to the container...
<div class="some_element_class"> <!-- delegate handler is here -->
<div>won't trigger your handler</div>
<a>will trigger your handler</a>
<a><span>will trigger</span> your handler</a>
<!-- this element newly added... -->
<a><span>...will also trigger</span> your handler</a>
</div>
"Also, in the example above, what does $(this) represent?"
this will represent the element that matched the "a" selector.
it means delegate() is invoked on the .some_event_class. and the a is selector string, click is event type string & function() is eventhandler function. delegate() method is used to handle the "live event" and for static events bind() is used. I hope this helps. feel free to ask if you have any doubts
Differences between bind() & delegate()
//Static event handlers for static links
$("a").bind("",linkHandler);
//Live event handlers for dynamic parts of the document
$(".dynamic").delegate("a", "mouseover", linkHandler);
Summary: they are just methods that bind event handlers to specific document elements.
The a is actually just a filtering selector, what will happen is that a normal click event is bound to .some_element_class, and anytime the event fires, the event target is traversed up to .some_element_class to see if there is an element that matches the filtering selector (tagname a). If it does, your callback is fired with this set to the first element that matched a selector in the bubbling path.
You can do something similar with bind:
$(".some_element_class").bind("click", function (e) {
var matches = $(e.target).closest("a", this);
if (matches.length) {
yourcallback.call(matches[0], e);
}
});
How to put into a grid cell not just a string <span>text</span>, but a string with an event handler?
This option does not suit me:
<span onclick='function(){...}'>click me</span>
I need to add, for example, such elements in one grid cell:
var $el1 = $('<button>clck me 1</button>').click(function(){...});
var $el2 = $('<button>clck me 2</button>').click(function(){...});
...
I use slick.dataview.
Don't.
Either handle click events via SlickGrid by using the onClick event it exposes or use event delegation on a higher level (container or document) to catch it. Add an attribute to the buttons to distinguish them later and decide which handler to execute.
Hy,
I want to bind an event to
< INPUT type=checkbox value='true' name='selectedRows[]' id='sel_id_" + i + "'class='editor-checkbox selected_rows' hideFocus />
but I couldn't find a good jquery selector. If I put an onclick event I can only call functions that are not in the $(function() { }); block and in this case I can't make use of some core functions.
Here is the link to it http://li.ro/4bJw
Thanks!
I've added a sample implementation at https://github.com/mleibman/SlickGrid/blob/master/examples/example-checkbox-row-select.html
This is part of the 2.0 release.