Is there a way to tell when a Widget is shown with GWT? - gwt

I'd like to respond to an even whenever my widget is made visible on a page done with GWT and UI Binder.
Is there anything similar to the onAttach() event handler (which fires when the widget is added to the DOM), pertaining to when the widget is actually made visible?
I'd like to be able to handle the even when the widget is shown because there are a few different ways of making it visible, and I'd like a single place on the widget itself that can handle this event.
Thanks

I know this is an old question, I have faced the same problem before. What I did was override the setVisible(boolean visible) method in the widget, then perform whatever I needed to do:
#Override
public void setVisible(boolean isVisible) {
super.setVisible(isVisible);
if(isVisible) {
// Do whatever you need to do with your widget
}
}

The widget should be visible once added to the DOM unless you've intentionally hidden it (i.e. with CSS or hid it behind another widget). Normally, onAttached() means its on the page. If you're using CSS classes to make it visible, write a setVisible(boolean isVisible) method to your widget and set the visibility class this way. If you have it behind another widget (i.e. in layers) then you'll need to write your only logic to determine when it's visible.

There is no browser event for this, but you could try this:
With your widget you could check the elements getLeftOffset (or similar method), if you get a positive value, you could fire your method, and set a flag to indicate that your onVisible() method had fired.
Then once the getLeftOffset returns a 0 you could reset your flag, ready to fire your event again.

Related

How to refresh Dialog when the data has change? Flutter

I'm a new Flutter developer and I have a problem, which I haven't been able to solve yet, even if I tried a lot.
I'm developing an App, where at some point a Dialog is opened(with showDialog()). In this Dialog there are 2 AutoCompleteTextField:
In the first one, the data will always be the same. So there is a list and the user needs to choose one of the choices. First AutoCompleteTextField code
In the second one, the data to be shown depends on the previous choice. In other words,
whenever an item from the previous list is chosen, the subdata of the item will be requested. Second AutoCompleteTextField code
The required data is fetched properly, however the dialog is not refreshing state so the suggestions of the second AutoCompleteTextField appears empty. When I close and enter again the suggestions of the second appears as they should.
To get notified when the data changes I use ChangeNotifier and Provider, but doesn´t refresh the Dialog (ChangeNotifier class). I also use StatefulBuilder to be able to use setState, but again, doesn´t refresh (Dialog code).
I would like to know if there is any other way to refresh the Dialog. Thank you!
PD: This is my first question in StackOverflow. I tried my best.
I think you need to use Provider.of(context) to be able to listen to the updates and refresh or add/update the data.
Provider.of(context)
I would create a widget class instead of the _widgetTask function and then use Provider.of(context) inside the widget build function like following (I think you can also try to add it inside the _widgetTask function but I dont know if this would work).
class WidgetTask extends StatelessWidget {
//WidgetTask contructor here..
#override
Widget build(BuildContext context) {
final odooData = Provider.of<OdooData>(context);
And then use the odooData to access the data/functions you need to update/listen to from the provider.
Also you can wrap the widget with GestureDetector so that you can update the widget upon tapping using the OnTap property.
flutterdartdialogrefreshproviderconsumer

Changing state of entire page vs one button in flutter

Ok, I am working on a media player app using flutter. Now when I press the play button, it changes to pause button. (Only the icon on the button changes)
The onPressed function for the button changes a boolean value and calls the setState() method.
It goes something like this.
bool _playing = false;
void _onPlayButtonPressed() {
setState () {
if (_playing)
_playing = false;
else
_playing = true;
}
}
I also have a function that returns the icon based on the value of _playing.
Widget _playButtonIcon() {
//This function has no setState() call
if (_playing)
//return pause icon
else
//return play icon
}
Everything works fine. The icon changes everytime I press the button. However as mentioned in docs and also in Flutter Demo App, setState() method calls the build method. Which redraws the entire widget tree including child widgets that are completely unchanged.
Is this approach justified or is this an overkill?
Do I have to put the button on a different Stateful Widget Class and call its build method via setState() everytime I tap this playButton?
What if I have other widgets that also changes the state of UI. Possibly changing different widgets?
What is the proper way to do this without having a performance hit?
Creating a play button that is a widget of its own with a state that maintains whether it is playing or not definitely makes sense. Now when you call setState on the parent widget it does call the build method, but as far as I know it does not necessarily redraw everything from scratch. If no changes are found in some of the embedded widgets it does not redraw them since they are already in the widget tree. Finally, it is okay to call setstate, however if your app starts getting bigger and you find yourself calling set state in too many places, and want to use global keys, I would advise looking into the Provider package, and making use of the ChangeNotifier/Consumer pattern.

Set focus to an Input in a gwtbootstrap3 Modal

I want to set the focus to a certain field (org.gwtbootstrap3.client.ui.Input) in a dialog (org.gwtbootstrap3.client.ui.Modal) before the dialog shows up. The use case seem quite common, if you have a dialog with a single field like the Upload text or Add feed dialogs right here. However I could not figure out how to set the focus to this particular gwtbootstrap3 component.
The Input component does have a setFocus(true) method. I assumed that setting the focus before showing the dialog would not work, which it doesn't. So the logical solution is to put the method call inside a ScheduledCommand. Like this:
Scheduler.get().scheduleDeferred(new ScheduledCommand() {
#Override
public void execute() {
textField.setFocus(true);
}
});
That usually works with GWT standard components, but does not seem to help in this case. I found a way to get notified once the dialog is shown through a ModalShowHandler. Like this:
modal.addShowHandler(new ModalShowHandler() {
#Override
public void onShow(ModalShowEvent evt) {
textField.setFocus(true);
}
});
I even tried to combine both, adding a deferred call to the handle. No luck. Any ideas?
You should be listening on the ModalShownEvent (note: Shown, not Show).
ModalShowEvent is fired when the modal is requested (for example, programmatically) to be shown.
ModalShownEvent is fired when the modal is actually shown.
This somewhat confusing naming is based on the events of the native Bootstrap Modal's events: show.bs.modal and shown.bs.modal.
ModalShownEvent combined with the usual Scheduler#scheduleDeferred should do the trick.

gwt generic page level click handler

I have this situation, where I display a success/error message on a page and then I want it to disappear when the user does anything on the page (I assume that that triggers a click event, I can ignore events like going to new tab/windows etc.).
I have other "uihandlers" and "clickhandlers" on the page. So if I click empty regions on the page only the hidemessage call fires, else if I click valid 'clickable' elements my hidemessage fires first followed by the relevant handler.
Is there a way I can achieve this without adding hidemessage to all my clickhandlers on the page?
Edit: The message widget is not a PopupPanel, so setAutohide(true) won't work. But it is exactly the behavior I'm looking for. The widget is a custom widget which extends Composite implements HasWidget, HasClickHandlers
You can do this on your error message:
myPopupPanel.setAutoHideEnabled(true);
It does exactly whet you need. You may also consider setting auto-hide on history events (mostly back button):
myPopupPanel.setAutoHideOnHistoryEventsEnabled(true);
EDIT:
If you are not using a PopupPanel, you can make your Widget implement EventPreview, and then:
public boolean onEventPreview(Event event) {
Element target = DOM.eventGetTarget(event);
boolean widgetIsTarget = (target != null) && DOM.isOrHasChild(getElement(), target);
setVisible(widgetIsTarget):

GWT DeckLayoutPanel sliding to a NEW (not-rendered-yet) widget? Doesn't work

I can't seem to slide to a new, not-rendered-yet widget added to a DeckLayoutPanel, no matter what I try.
It appears without the slide transition if it's never been rendered before.
However, when I do showWidget(...) back and forward to the new widget, then the slide transition works fine.
Has anybody been able to slide to a not-rendered-yet widget in DeckLayoutPanel? If so how?
I need this functionality.
You can use the scheduleDeferred comand. This will make sure that your slide command is executed, when the widget is actually shown.
It defers some code until after the browser redraws the page (if needed) and pending events are processed (that is after the mouseup and click if this is done in mousedown)
Source
Docu
Usage:
Scheduler.get().scheduleDeferred(new ScheduledCommand() {
#Override
public void execute() {
Scheduler.get().scheduleDeferred(/*Your silider comand*/); // reschedule
}
});