I need to set the ENTER key to navigate between enabled fields placed on a com.vaadin.ui.Panel. How can i programmatically do this?
This is my intent but doesn't now how to send a keypress:
Action ENTER_KEY_ACTION = new ShortcutAction(
"Enter key"
, ShortcutAction.KeyCode.ENTER
, null
);
public Action[] getActions(Object target, Object sender) {
return new Action[] { ENTER_KEY_ACTION};
}
public void handleAction(Action action, Object sender, Object target) {
if (action == ENTER_KEY_ACTION ) {
ENTERKeyHandler();
}
}
protected void ENTERKeyHandler(){
//
//here i need to send a TAB keyPress
//
}
this code work perfectly up to now but isn't ended. I don't know if there is another way to accomplish this?
please sorry my English too.
The AbstractComponent class provides a method for this (Your field object extends AbstractComponent). The method is called fireEvent(Component.Event event).
You could try to send an event to the registered listeners with this approach.
Try to add a FocusListener to your fields in the Panel, which keeps track of the currently focused field. You also have to know the tabbing order of the fields on the server-side and in the ENTERKeyHandler() method you call field.focus() for the field to be focused.
Related
We are using a grid to present some data. This grid is not using a data provider but setting its items.
We are working on buffered modd, but we still want to show a modal informing what are we about to save, with the posibility to save or cancel.
SaveEditor method has been removed from grid class in our current version (8.4.0), so cant do it that way.
I have come to a close solution but with some remaining problems.
I have extended grid component to be able to create my own editor:
public class MyGridComponent extends Grid<MyData> {
public MyGridComponent (Class<MyData> beanType) {
super(beanType);
}
#Override
protected Editor<MyData> createEditor() {
return new MyGridEditor(this.getPropertySet());
}
}
On my editor I have overriden following methods:
#Override
protected void doEdit(OutcomeWagerLimit bean) {
copyMyBean = bean;
super.doEdit(bean);
}
#Override
public boolean save() {
String desc = copyMyBean.getDescription();
StringBuilder captionBuilder = new StringBuilder()
.append("Save ")
.append(desc)
.append("?");
StringBuilder messageBuilder = new StringBuilder()
.append("Do you really want to save ")
.append(desc)
.append("?");
openConfirmMsgBox(captionBuilder.toString(), messageBuilder.toString(),() -> super.save(), ()->super.cancel());
return true;
}
With this code clicking on save opens my confirmation modal. If clicking on save, everything works flawlessly, but clicking on my modal cancel which will call to EditorImpl.cancel() method, acts in a weird way. Clicking cancel on my modal will close edition mode, but if I edit again any other row (double clicking on it) grid's save and cancel buttons (not the modal ones) stop working. Not launching any request from client to vaadin's servlet.
Does anyone know any possible solution to this or a better way to reach what I'm trying to achieve?
Thanks in advance
Morning,
Just managed to do it. Since not using dataprovider but normal list, I am the one responsible of saving data in other saveEventListener. That is the moment to present modal and in the "ok" case persist it in database.
So there is no need to override EditorImpl save method and do it in a saveEventListener.
Thanks
I need to solve a simple problem, but yet I have not been able to found out any solution yet.
I have a simple DropDownChoice with AJAX onChange() JS event. I need to add a confirm box before the onUpdate() action is done - this is not difficult, BUT I need to display the confirm box only if the new selected value of the DropDownChoice is X (one certain value), and do not display the confirm box in any other case. Is it doable?
Short example snippet:
DropDownChoice<Integer> choice = new DropDownChoice<Integer>("id", new Model<Integer>(0));
choice.add(new AjaxFormComponentUpdatingBehavior("onchange") {
#Override
protected void onUpdate(AjaxRequestTarget target) {
// do some stuff
}
#Override
protected void updateAjaxAttributes(AjaxRequestAttributes attributes) {
super.updateAjaxAttributes(attributes);
attributes.getAjaxCallListeners().add(new AjaxCallListener() {
#Override
public CharSequence getPrecondition(Component component) {
return "return confirm('Really?')"; // I NEED THIS DISPLAYED CONDITIONALLY
}
}
}
}
I don't know how to access the "choice" model object (converted input...) with the proposed value to add it to a condition in updateAjaxAttributes() method.
Thank you.
I think you should go for a JavaScript-based solution. The code of AJAX call listener is executed in a scope where you can use variable attrs. This variable contains the parameters used to perform AJAX call, including the id of the component. In this way you could check for selected value.
See more at http://wicket.apache.org/guide/guide/ajax.html#ajax_5
I need to recreate new page instance on every page load (also when user pressed Back button).
So I overrided OnBackKeyPress method:
protected override void OnBackKeyPress(CancelEventArgs e)
{
base.OnBackKeyPress(e);
if (NavigationService.CanGoBack) {
e.Cancel = true;
var j = NavigationService.RemoveBackEntry();
NavigationService.Navigate(j.Source);
NavigationService.RemoveBackEntry();
}
}
The problem is that I can't handle case when user press back button to close CustomMessageBox dialog. How can I check it? Or is there any way to force recreation of page instance when going back through history state?
Why do you need to recreate the page instance? If you are simply trying to re-read the data to be displayed, why not put the data loading logic into OnNavigatedTo()?
Assuming that is what you are actually trying to achieve, try something like this...
public partial class MainPage : PhoneApplicationPage
{
// Constructor
public MainPage()
{
InitializeComponent();
// don't do your data loading here. This will only be called on page creation.
}
protected override void OnNavigatedTo(NavigationEventArgs e)
{
LoadData();
base.OnNavigatedTo(e);
}
MyViewModel model;
async void LoadData()
{
model = new MyViewModel();
await model.LoadDataAsync();
}
}
If you also have specific logic that you need to run on first construction of the page vs. on a back key navigation, check the NavigationMode property of the NavigationEventArgs object that gets passed to OnNavigatedTo.
if(e.NavigationMode == NavigationMode.New)
{
//do what you need to do specifically for a new page instance
}
if (e.NavigationMode == NavigationMode.Back)
{
// do anything specific for back navigation here.
}
Ha, in the near thread, i have opposite question :)
What about MessageBox - it depends, which one are you using. It can be custom message box, for example. Anyway, try to check MessageBox.IsOpened (or alternative for your MessageBox) in your OnBackKeyPress().
Another solution is to use OnNavigatedTo() of the page you want to be new each time.
Third solution: in case you works with Mvvm Light, add some unique id in ViewModel getter, like
public MyViewModel MyViewModel
{
get
{
return ServiceLocator.Current.GetInstance<MyViewModel>((++Uid).ToString());
}
}
This would force to recreate new ViewModel each time, so you'd have different instance of VM, so you would have another data on the View.
I have a property and depending upon it's state (say A and B) I either show a usercontrol of animation or a image.
Now, if the property changes, I want to trigger the datatemplate selector again. On searching, I found that in WPF I could have used DataTemplate.Trigger but it's not available in WP.
So, my question is
Is their a way to trigger datatemplate selector so when property changes from state A to B, then appropriate usercontrol gets selected. If yes, then please give some example how to implement it.
Also, as there are only two states, if think I can use Converter to collapse the visibility. For basic if else situation, I will need to write two converters.( Can I somehow do it using one converter only?)
Here is the exact situation.
If state == A :
select userControl_A
else : select userControl_B
Also,
Will the animation usercontrol will effect the performance when it's in Collapsed state?
EDIT- Just realized, I can use parameter object to write just one converter.
You could implement a DataTemplateSelector like described here.
I use it and it works pretty well.
EDIT:
If you need to update the DataTemplate when the property changes, you should subscribe to the PropertyChanged event of the data object in the TemplateSelector and execute the SelectTemplate method again.
Here is the code sample:
public override DataTemplate SelectTemplate(object item, DependencyObject container)
{
City itemAux = item as City;
// Subscribe to the PropertyChanged event
itemAux.PropertyChanged += new System.ComponentModel.PropertyChangedEventHandler(itemAux_PropertyChanged);
return GetTemplate(itemAux, container);
}
private DataTemplate GetTemplate(City itemAux, DependencyObject container)
{
if (itemAux != null)
{
if (itemAux.Country == "Brazil")
return BrazilTemplate;
if (itemAux.Country == "USA")
return UsaTemplate;
if (itemAux.Country == "England")
return EnglandTemplate;
}
return base.SelectTemplate(itemAux, container);
}
void itemAux_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
{
// A property has changed, we need to reevaluate the template
this.ContentTemplate = GetTemplate(sender as City, this);
}
i have a little problem with javafx. i added a change listener like this:
private final ChangeListener<String> pageItemSelected = new ChangeListener<String>()
{
#Override
public void changed(ObservableValue<? extends String> observable, String oldValue, String newValue){
pageGotSelected(newValue);
}
};
now to the problem: if i change an page item like this:
guiPageList.setValue(model.getCurrentTargetPage());
the event gets also(as it get by selecting something with the mouse or key) fired. is there a way to disable the event firing or another way?
i need the event only, if the element got selected by the user and not if i change it with the setValue() function...
perhaps consuming the event, but i donĀ“t know what kind of event this would be.
thanks in advance!!!
You can temporarily remove the listener and add it again:
guiPageList.getSelectionModel().selectedItemProperty().removeListener(pageItemSelected);
guiPageList.setValue(model.getCurrentTargetPage());
guiPageList.getSelectionModel().selectedItemProperty().addListener(pageItemSelected);
Alternatively you could decorate the listener with another listener implementation, the code would be something like:
class InvalidationListenerEventBlocker implements InvalidationListener {
InvalidationListener decoratedListener;
boolean block;
public void invalidated(Observable observable) {
if(!block) {
decoratedListener.invalidated(observable);
}
}
}
Add a setter for the block boolean and send the listener in through the constructor. Set block to true to stop events.
This is very old question, but I came to some solution I personally use, that's reusable and does not require storing a reference to the listener (but it needs a reference to the exposing/muffling property thou).
So first the concept: we're going to create lambda (InvalidationListener), that is going to be called only if above mentioned exposing/muffling property is set to true/false. For that we are going to define another functional interface that provides described behavior:
#FunctionalInterface
private interface ManageableInvalidationListener
extends InvalidationListener {
public static InvalidationListener exposing(
BooleanProperty expose,
ManageableInvalidationListener listener) {
return ob -> {
if (expose.get()) {
listener.invalidate(ob);
}
};
}
public static InvalidationListener muffling(
BooleanProperty muffle,
ManageableInvalidationListener listener) {
return ob -> {
if (!muffle.get()) {
listener.invalidated(ob);
}
}
}
public abstract void invalidated(Observable ob);
}
This interface defines two static methods we're going to use in our code. We pass a steering property as first argument (it will tell if listener should be called) and actual implementation to be performed, when it will be called. Please note, that there is no need to extend InvalidationListener, but I'd like to keep ManageableInvalidationListener in sync with InvalidationListener.
So we would call exposing if we need to create a (manageabale) listener that would notify the (invalidation) listener if expose property has value of true. In other case we would create the listener with muffling, if true of the steering property would mean, well, to muffle the notification.
How to use it?
//- Let's make life easier and import expose method statically
import static ManageableInvalidationListener.exposing;
// ...
//- This is the steering property.
BooleanProperty notify = new SimpleBooleanProperty(true);
//- This is our main property with the listener.
ObjectProperty<Foobar> foobar = new SimpleObjectProperty<>();
//- Let's say we are going to notify the listener, if the
// notify property is set to true.
foobar.addListener(exposing(notify, ob -> {
//- Here comes the InvalidListener code.
}));
And then somewhere in the code:
//- Listener will be notified as usual.
foobar.set(new Foobar());
//- Now temporarily disable notifications.
notify.set(false);
//- The listener will not get the notification this time.
foobar.set(new Foobar());
//- Re-enable notifications.
notify.set(true);
Hope this somehow helps. You're free to use the code in this post as pleases you.