One Presenter needing Access to another Presenter's State in GWT MVP - gwt

I am making an application where I have three main Presenters.
In one say "ListPresenter", I have a Tree with a list of cities.
In one say "WritePresenter", I type in some text and hit update. The update is for one of the cities.
In one say "ShowPresenter", I show the update if and only if an update is availaible for that city which is currently clicked in our list.
Now the way I am doing it is...
WritePresenter fires an event on the EventBus with details of for which item the event is being fired. ShowPresenter listens to these events and based on the ListPresenter state needs to update itself.
Now how should ShowPresenter get access to ListPresenter state. I could just get a refrence of it from the Class which instantiate ListPresenter. But that dosent seem to be a good design idea. Also seems to be increasing coupling.
What can be the best possible way around?

How about making ListPresenter fire another event that ShowPresenter would be subscribed to. That event would be fired if, and only if, ListPresenter is in such a state that ShowPresenter should be updated.

Related

gtm.start firing twice (or more) on the same page causing two Container Loaded events

I have an issue on any page within a specific domain, where for every page load I have two Container Loaded events. Now this wouldn't bother me normally, but the DataLayer object I need only loads in the second gtm.start event, while my tag fires on the first gtm.start, so that the DLV is undefined when I need it.
Can I do anything GTM-side so that the DLV populates on the first Container Loaded event?
enter image description here
The container loaded more times than needed.
I think the problem is your website has 3 GTM installed. So the sequence here is very important.
You might need to check with your engineer or you can do it yourslef.
Currently the order looks like:
GTM-A.js
Datalayer you need
GTM-B.js
GTM-C.js
So I would recommend your order should adjust to
Datalayer you need
GTM-A.js
GTM-B.js
GTM-C.js
The core idea is make your datalayer push before any gtm.js code. This would make sure the GTM containers detect the datalayer you need when loading.
Otherwise. Make the datalayer push with an event name. So you can make your page_view event with that datalayer event.
But not very recommend this way. Only if you can not modify the order.

Where can I found documentation about page lifecycle events?

I am using cdp (https://github.com/mafredri/cdp) in order to use devtools protocol to generate a pdf of a page. But first I need to know when the page is completely loaded. I found that the networkIdle event can help me to know when this occurs. But, I have troubles because the networkIdle event sometimes fired twice. Then I need to know when this one is fired
There are two parts for what you're looking for.
First of all, the reason the event is fired twice. When a new tab (target) is created, the first page it loads is about:blank. You get lifecycle events for this page as well. The second time the load event is fired is the one you're looking for (if you're using Page.lifecycleEvent).
Now, to handle the second matter - there are also other events you can use. The basic one for page loading is Page.loadEventFired, which, as far as I recall, will only be fired for the actual page (but I could be wrong about this one).
Important note: If you're using lifecycle events, they are fired for each frame separately, meaning that the main frame might finish loading before the sub frames are loaded. Page.loadEventFired has a different behavior and waits for all frames to fire their load event.
Here is a good article on the page lifecycle api.
Another possible solution could be:
document.onreadystatechange = function () {
if (document.readyState === 'complete') {
run the screenshot code...
}
}

Where to put state that's needed by different GWT activities?

I'm currently working on a GWT application and I'm still a little fuzzy on how it all fits together (the joy of having to make changes without first coming to an understanding of the whole framework, although that might be difficult anyway).
We have a few Activities that all correspond to parts of the UI (e.g. main content, a toolbar and a list of things). I'm not really sure whether that's even how Activities are intended but I guess I can't really change that easily now. My problem now is that the list of things holds state (the current selection) that the main content also needs and in a way the toolbar too (at least the toolbar currently has it – I'm beyond asking).
But what would actually be an appropriate place to store that? I guess coupling the actual view implementations together and storing the selection only in the list isn't such a bright idea.
I see two main solutions here:
keep the state within each activity and keep them synchronized through events (on the EventBus). That is: the "list of things" has a current selection, main view has one too, so does the toolbar; and each time that value changes, the activity that's making the change fires an event on the event bus so that the other activities can update their state, so that all activities have the same value in their own state.
use a singleton object (if you're using GIN and dependency injection, simply annotate the object with #Singleton and inject it in all the activities) to keep the state at a central place. The activities register event handlers on the state holder object to be notified when it changes. That is, each time an activity calls setCurrentSelection (for example), an event is fired (for example a ValueChangeEvent), and because all activities listen for it, they can update their view or whatever depending on the new value. You can choose to either dispatch the event on the event bus (similar to the PlaceController) or have the state holder implement HasValueChangeHandlers. Just make sure to unregister the handlers when the activities stop to avoid memory leaks (dispatching on the event bus makes it easier: simply register the handlers on the bus passed as argument to the start method and they'll be unregistered automatically when the activity stops, and you don't even have to think about it).
Actually, PlaceController is a good example of such shared state (the current place).

WorkflowView force refresh when new child Activity is added

My application is using workflow designer rehosting to let end-users develop workflows. I have an Activity available that requires the user set some state. To accomplish this, in the designer I override Initialize(Activity) and show a form which I then use to set values in my Activity. This is for setting the state when the Activity is initially added. I also have a double click event handler in the designer in case they need to edit that state later.
I now have a situation where, depending on the values in the form, I may need to add or remove a child activity. I've been successful in adding the activity, but not always in getting it to show up in the designer.
When Initialize is called, there are no child activities. I may need to add a child Activity. At this point, it works fine and shows up in the designer. The problem happens when they edit it later by double clicking. In my designer, I override OnActivityChanged to detect this. I make the same call to add a child, however the designer is not getting updated. Oddly enough, when the situation is such that the child is removed, the view updates fine.
Stepping through with the debugger shows that I am adding a child activity to the Activities collection. Normally when I have problems updating the view, I can make a call to IComponentChangeService.OnComponentChanged, but I can't seem to find a way to make this work.
Any suggestions?
It looks like I needed to use RemoveActivities and InsertActivities in the designer. It seems as if the designer doesn't listen to list change events on the Activities list. Does anyone know if this is how it's supposed to work?
Have you tried this in your OnActivityChanged event handler?
TypeDescriptor.Refresh(e.Activity);
For my situation, I determined I needed to use RemoveActivities and InsertActivities.

GWT-EXT - What is the best way to widgets to a specific ContentPanel after an event?

first post don't hurt me :)
I am using a BorderLayout with the usual North, West, Center, South Panels. On the West ContentPanel, I've got a Tree. If an event (OnClick)occurs I want a particular dialog box displayed on the Center ContentPanel.
What is the best way for me to do this? Currently I'm using a function called returnPanel() that returns the center ContentPanel. In the event handler I call this function (MainWindow.returnPanel().add(myDialog)).
The way you are doing it is intuitive and works, but will start causing hell when the application grows, because different parts of the application are strongly coupled. The solutions to this problems are the MVC design pattern and the observer design pattern.
Ideally, using the MVC pattern, you don't want any widget to 'know' of any other widget. There is only class that knows all the widgets, which is the Controller. Anytime one widget needs to message/signal another widget, it tells it to the Controller class, which relays the message in the appropriate way to the appropriate widget. In this way, the two widgets are decpoupled and one can change without breaking the other. You may want to use an enum to enumerate all possible actions to which the controller has to responsd.
If your widget has to call only the Controller when an event occurs, you may simply call an aptly named (static) method on it and be done with it. However, as soon as multiple other classes needs to be informed of an event, you are better of using the Observer pattern, which allows you to signal multiple other classes, without changing your class. It simply calls notifyPObservers() in the eventHandler and that's it. How many listeners there are, and what type they are, is irrelevant. This way, you also decouple a class from it's listeners. Even if only the Controller listens, it may be advisable to use the pattern, as it clearly seperated the 'call back' code from the other code in the classes.
BTW, this has nothing to do with GWT or even Java in particular.