how to use eventBus.removeHandler in mvp4g? - gwt

I wanted to delete/clear all the instances of a presenter before firing an event. The documentation says to use eventBus.removeHandler(handler), I am not figure out how to get the handler object from the presenter class
Presenter has multiple=true attribute set.

If you have declared a presenter with "multiple="true"
#Presenter(view=OneView.class, multiple=true)
public class OnePresenter extends BasePresenter<IOneView, OneEventBus>{...}
you add the presenter to the eventbus by calling:
OnePresenter presenter = eventBus.addHandler(OnePresenter.class);
and remove the presenter by calling:
eventBus.removeHandler(presenter);
Here you will find the documentation:
https://github.com/FrankHossfeld/mvp4g/wiki/04.-Defining-presenters,-views-&-Services#multiple-presenter
In mvp4g you can easily activate and deactive presenters thanks to the activate/deactivate attribute of the #Event annotation. (https://github.com/FrankHossfeld/mvp4g/wiki/03.-Defining-EventBus#activatingdeactivating-presenters)
If you need to get the control just before a presenter handles an event, you can override the onBeforeEvent-method. (https://github.com/FrankHossfeld/mvp4g/wiki/04.-Defining-presenters,-views-&-Services#on-before-event)

Related

How to catch events of a class in a class helper?

I want to create a helper for TCustomQuery, TQuery, TTable and so on... With a LastRecordPosition property, which I will get with OnBeforeScroll setting that property from RecNo.
How do I create that trigger in that helper class to catch the event without interfere in an user's OnBeforePost if he/she needs one?
I use FireDAC or ZeosLib for older versions.
To intercept the OnBeforeScroll event without interfering with the user's OnBeforeScroll event handler, you need to override each component's virtual DoBeforeScroll() method. However, a class helper cannot override any virtual methods of the class it is helping. So, you will have to instead either:
write new classes that are derived from each base component class you want to intercept (type TMyCustomQuery = class(TCustomQuery), etc), and then the user must use those new component classes in their code instead of the originals.
(XE and later only) use Delphi's TVirtualMethodInterceptor class to hook the virtual DoBeforeScroll() method of specific component object instances (not the classes themselves) without having to write any derived classes.
The alternative is to write a class, possibly a Generic class, that the user has to instantiate for each component object instance, and the class can then subclass its associated component (possibly with RTTI) to capture and replace the user's OnBeforeScroll event handler with its own, and then its event handler can call the user's event handler when needed.

Gin injecting in a shared (client server) object - "IsTreeItem"

I have an object that implements "IsTreeItem". The Object is displayed as a two level tree item. Each tree item is built with a check box.
I need to know when a check box is changing value - so i am listening to ValueChangedEvents.
The first problem is that the Tree built with such items only fires SelectionEvents. If selection is changing the check box the ValueChanged event is fired afterwards - so there is no way to listen to events inside "IsTreeItem" from Tree.
So i let my "IsTreeItem" fire its own element. So i (field)injected an EventBus and used it to fire the event if "ValueChanged".
The Problem is that my "IsTreeItem" is an Object sent from server (it is in shared package and serializable). The object is instantiated on server (EventBus is not ionjected) and "asTreeItem" is called on client.
Is there a way to inject the EventBus in the Method TreeItem asTreeItem() in some way? Or are there any other means to let some one outside know if a check box has changed its value.
GIN can do member injection on already created instances.
You have to create a method in your Ginjector interface that takes such an instance as argument, with a return type of void.
Note that because no reflection is done on the client, GIN will only inject fields and methods from the class used as the argument type (and its super-classes).
#GinModules(MyGinModule.class)
interface MyGinjector extends Ginjector {
…
void injectIsTreeItemMembers(IsTreeItem item);
}

how (multiple=true) presenter and view can be initialized with parameters using eventBus.addHandler?

With the Mvp4g architecture, (Only)one instance of the view (injected using #Presenter annotation)is associated with its presenter.
In my case, I have a EntityView with its Presenter EntityPresenter.
whenever user clicks on an Leaf node of a Navigator tree,
I add a new Tab into TabSet. And this new Tab will contain an EntityView.
So, I will have as many EntityView as many Tab in the TabSeT.
I have set multiple=true for EntityPresenter.
EntityView's constructor accepts one argument.
#Inject
public EntityView(final Record view) {
//some initialization
}
Question is, where I do (from another presenter):
EntityPresenter presenter = eventBus.addHandler(EntityPresenter.class);
I have one argument Record params which I want to pass to EntityView's constructor, how to do that?
and annotating constructor(accepting argument) with #Inject will inject EntityView to EntityPresenter ?
I suggest to use an EventHandler - that's a presenter without a view in mvp4g - which get an event showEntity(long key). In the onShowEntity(...) - method you can create the presenter with the statement:
EntityPresenter presenter = eventBus.addHandler(EntityPresenter.class);
With that reference of the instance, you can esaly set the key in the presenter.
But keep in mind, you have to manage your presenter instances by yourself, when using multiple=true.

Can I register a custom model binder somewhere other than Global.asax?

It would be handy to limit the scope of a custom model binder for just a specific controller action method or its entire controller. Hanselman wrote a sentence that implied alternative locations for custom model binder registration but never seemed to finish the thought:
You can either put this Custom Model Binder in charge of all your DateTimes by registering it in the Global.asax
Is it possible to make these registrations at a smaller scope of the controller system? If so, is there any reason to avoid doing so outside of the Global.asax MvcApplication (e.g., performance reasons)?
As I was closing the tabs I opened for this question that I hadn't reached before giving up, I found someone with an answer. You can assign a ModelBinderAttribute to your view models:
[ModelBinder(typeof(SomeEditorModelModelBinder))]
public class SomeEditorModel {
// display model goes here
}
public class SomeEditorModelModelBinder : DefaultModelBinder {
// custom model binder for said model goes here
}
While it wasn't quite what I was looking for, it is even more specific than registering it for a controller or controller method.
Update
Thanks to Levi's comment pointing out a much better solution. If you are consuming the object with a custom model binder in an MVC action method directly, you can simply decorate that method's parameter with the ModelBinder property.
public ActionResult SomeMethod([ModelBinder(typeof(SomeEditorModelBinder))]SomeEditorModel model) { ... }

Using GIN and mvp4g

I'd like to use gwt-dispatch Command Patter implementation in my app. I'm using also mvp4g. How can I make DefaultDispatchAsync available to inject into my presenters using GIN or make it globally available, so I can access it from my presenters?
You need to setup a bind for the DefaultDispatchAsync class in your gin module. This will setup the binding for the DispatchAsync interface that the DefaultDispatchAsync class implements. You can then add a DispatchAsync to your presenter constructor and have it injected by gin as required.
I normally then have my presenters contain a private DispatchAsync member, which i assign the injected DispatchAsync argument to inside the constructor. Then the dispatch can be used in the presenter class as required.
So in your GinModule's configure method, add the line
bind(DefaultDispatchAsync.class);
Then on your presenter constructor,
#Inject
public TestPresenter(/*Other injected arguments*/, final DispatchAsync dispatcher) {
this.dispatcher = dispatcher;
}