Appcelerator - Notify parent view if something happen on child view - view

How should I get info about child view's events on parent view?
For example:
I pass and argument to the child (Alloy.createController('myChildView', { info: test }).getView()). Then I work with it and set a global variable from false to true (Alloy.Globals.childPrecessed = true). After that, I can spent any time on this view, but when I click on a button which fires a hide event, I should process the info from parent view.
My first thought was I fire az appwide event (myChildHide), and listen for it in the parent view. If I catch it, then I process the info, and destroy the listener...
Is this the best method? I'm not sure...
Has anybody better solution for this?
Thanks!

I am a fan of event listeners, so I think your approach is a good one.
What I normally do is to initiate the event listener right before I need it to be effective, i.e. in the method opening the child window. But first I use backbone events for simple event triggering. See Fokke Zandbergen's article for further info. So assuming you have set up a "dispatcher" then I would do something like this:
function openChild(){
dispatcher.on("child-calling", doChildsWork);
// ... open child view
}
Then in the doChildsWork I would disable the event handler once called:
function doChildsWork(args){
dispatcher.off("child-calling");
// ... do work initiated by child view using args...
}
And finally in the child view (assuming you have set up a "dispatcher") you would do something like this:
function doChildsWork(){
// ... Tell parent to do some work
dispatcher.trigger("child-calling",{test:true});
// ... continue whatever is going on in child
}
I use this approach a lot - and it works well :-)
/John

Related

How to add an event listener to a Kendo UI view?

$('#my-view').on('show', showHandler)
Doesn't work. Using data-show is not an option either because the code that sets/unsets the event is within class that is instantiated later. Also creating the view programatically and passing in the event handler doesn't work because I need to set the event on/off at different times.
Is this not possible with kendoUI? If not, why? This seems like such an incredibly obvious feature to relay those events to the element themselves similar to what is possible with jquery ui widgets.
This works:
var view = $('#my-view');
var widget = kendo.widgetInstance(view);
widget.bind('show', showHandler);
Better answer, just delegate the events yourself so the code in the question actually works:
<div data-role="view" ... data-show="onShow">...</div>
and
function onShow () {
this.element.trigger('show');
}
Now the it works :). The problem I still has was that 'show' isn't triggered when a view is first shown if it is the first view shown. Er, so yeah I had to add some extra code for that too like this:
if ($('#my-view').is(':visible')) {
$('#my-view').trigger('show');
}
Lame but it works.

How to use Backbone.EventBinder with views

Referring to this post on Backbone.EventBinder, I am lost on how to use EventBinder with Backbone views (which is the most popular use case). Is it still recommend to add a close() method to the Backbone.View prototype and a onClose() method to the view as suggested in this post? Also where does one store the binder object, so that binder.unbindAll() can be called on close? What is the recommended way to close child views (e.g. a parent view on a collection which has child views on the associated models). A working example would be a great addition to the Backbone.EventBinder project.
Yes, you should still add a close method to your views. The EventBinder does not negate any of what that Zombies post says. Rather, it helps to automate a lot of the process by making it easier to unbind all of your events within the view.
Take a look at the Marionette.View source code for an example of how it's used:
https://github.com/marionettejs/backbone.marionette/blob/master/src/marionette.view.js#L9
https://github.com/marionettejs/backbone.marionette/blob/master/src/marionette.view.js#L16
https://github.com/marionettejs/backbone.marionette/blob/master/src/marionette.view.js#L97
If you're using Marionette, you don't need to add the close method yourself, or add the event binder yourself. That's handled for you.
If you want to add this to your own views, it's easy:
MyView = Backbone.View.extend({
initialize: function(){
// add the event binder
this.eventBinder = new Backbone.EventBinder();
// bind some stuff
this.eventBinder.bindTo(this.model, "change:foo", this.doStuff, this);
},
close: function(){
// ... other stuff
this.eventBinder.unbindAll();
}
});

MvvmCross : databinding programmatically

I think I need to bind data programmatically to solve my problem.
I use a TabHost which hosts 2 Tabs.
I need to load the MvxBindableListView in the second tab when TabHost appears and keep the first tab as default tab.
What I'm doing is starting the second tab activity without problem because I check the process using this code:
protected override void OnViewModelSet()
{
SetContentView(Resource.Layout.Page_ActivityView);
System.Diagnostics.Debug.WriteLine("activityView started");
MvxBindableListView mvxBindableListView = FindViewById<MvxBindableListView>(Resource.Id.mvxBindableListView);
mvxBindableListView.ChildViewAdded += new System.EventHandler<Android.Views.ViewGroup.ChildViewAddedEventArgs>(mvxBindableListView_ChildViewAdded);
}
"activityView started" is displayed in output debugger, but MvxBindableListView.ChildViewAdded event isn't raised, only when I click the second tab.
So I suppose that MvxBindableListView is not databound.
Thanks in advance to help me loading my second tab programmatically.
I think ChildViewAdded is an event that occurs when the ListView is rendered - at that time when it needs to 'draw list items', then it will ask its adapter for child Views for the screen. As you scroll down the list, it will then ask for more child views - but it will also reuse views - so for a simple list you should only ever (hopefully) get N+1 calls on ChildViewAdded for a list which shows N items at one time.
So it's perfectly possible for a list to be databound but never to call ChildViewAdded - that won't get called until the list is 'drawn'
Sadly the Xamarin docs aren't helpful here - http://docs.mono-android.net/monodoc.ashx?link=E%3AAndroid.Views.ViewGroup.ChildViewAdded
Note: if you do actually want to bind programatically, then you can do this to - using Bind() methods and extension methods. However, I haven't expanded on that here - as it doesn't sound like that's actually what you need!

ember js subviews and didinsertelement event

I'm writing an Ember.View, which turns a tree structure into a menu. I need recursion for this, so what I use in my view template is a {{view}} helper, which recursively calls itself to build a nested <ul><li> structure.
What I need is a hook to call some jQuery plugin to turn this structure into the menu. When I call the plugin from the didInsertElement event, the subviews haven't rendered yet. How can I run code when all subviews have finished rendering?
Try calling the plugin within Ember.run.next() which should call it after the current run loop is complete... which I believe won't happen until all of the subviews are created.
Docs -> http://docs.emberjs.com/symbols/Ember.run.html
This might help in your situation, I made a handlebars helper that tells you when the sub-section has rendered. By default it sends an event to your view object, so each of your instantiated views would receive an event whenever they rendered.

JQuery Ajax - Rebinding elements with the context param instead of delegate?

So we all know in an ajax update events must be rebound to new dom elements. Yes delegate is an option, but delegate doesn't work for all scenarios. For instance delegate won't help for something that needs to be done simply on load rather than on a click event.
Rather than split my code into delegate handlers and handlers that need to be rebound on updates, I would rather define a single method with a context parameter that gets called every time the page changes like so:
function onPageUpdate(context) {
$('a', context).click(...); // event handlers
$('.chart', context).addClass(...); // load handlers
}
On dom ready this will be called with the context parameter null. On an ajax update the context will container the new dom elements. This way I'll never have to worry about delegating or ajax updates again.
I'm having trouble getting this to work however. Given the ajax callback:
function onSuccess(data) {
// data contains new dom elements like: <div><a>Click</a><span>chart<span></div>
// replace old elements with new ones
$('a').replaceWith('a', data);
$('span').replaceWith('span', data);
// call pageUpdate with the new context
onPageUpdate(data);
}
Is it possible to make this work like I expect? The replacing works fine, but onPageUpdate isn't binding anything to these new elements, I don't know if thats because the context is just a string object or what. Can anyone think of a way to make this work?
In my mind this is a better solution than delegate, because theres only one method for all handlers and only the elements that need a binding will own it.
From jQuery() - jQuery API
jQuery( selector [, context] )
selector A string containing a selector expression
context A DOM Element, Document, or jQuery to use as context
If the context isn't the correct type - such as passing a string - it's simply going to be ignored. Try wrapping your HTML string in a jQuery object, then use that as the context for your selectors, like so:
var $context = $(data);
$('a').replaceWith('a', $context);
$('span').replaceWith('span', $context);
// call pageUpdate with the new context
onPageUpdate($context);
I won't answer to your question, Anthony Grist's answer is quite right, but there are some things you said that I don't understand. Could you explain them to me ?
For instance delegate won't help for something that needs to be done simply on load rather than on a click event
Sorry but I don't get it, do you have an example ?
In my mind this is a better solution than delegate, because theres
only one method for all handlers and only the elements that need a
binding will own it.
I don't get it too:
only one method: which method are you talking about ?
only the elements ... will own it: it's also the case with delegate, and more, if you have let's say 10 anchor element, only ONE handler would be bound, instead of 10 in your solution
On your method onPageUpdate you're mixing two things: event handling ($("a").click(...)) and DOM modification ($(".char").addClass(...)). Maybe that's why you're confusing about delegate's ability to resolve your problem.

Resources