Showing posts with label SuggestBox. Show all posts
Showing posts with label SuggestBox. Show all posts

Monday, 25 February 2013

GWT: SuggestBox und Tabulator KeyStroke in der CellTable

GWT 2.5

In letzter Zeit handelten meine Beiträge größtenteils von CellTable und SuggestBox und auch diesmal geht es so weiter. Folgende Problemstellung: Ich habe in der Table die Möglichkeit geschaffen daß man mit Tab-Sprüngen die Zellen wechselt, hier der Link dazu wie man das macht: stackoverflow Frage + Antwort.

Nun ist es aber mal so, das wenn man mit Tab die Zelle wechselt der KeyUp Event schon in der neuen Zelle stattfindet und hier beginnen die Probleme: Die SuggestBox glaubt durch das KeyUp das der User etwas in der TextBox verändert hat und läuft gleich mal los um Vorschläge einzuholen... für meine Erfordernisse ganz und gar unnötig bzw. will ich nicht daß der im Feld stehende Wert gleich mal dazu verwendet wird Services aufzurufen.

Die SuggestBox behandelt das in der privaten Methode addEventsToTextBox(), und da privat kann man das Teil nicht einfach überschreiben. Eine Möglichkeit ist es nun die gesamte Klasse zu kopieren und bei der Behandlung des KeyUp Events den Tab KeyStroke daran zu hindern die Methode refreshSuggestions() aufzurufen. Das funktioniert, nur ist das Kopieren ganzer Klassen für eine Zeile Änderung und die Übernahme der Package Struktur (notwendig weil die SuggestBox auf protected Teile im Package com.google.gwt.user.client.ui zugreift) einfach nur gruselig.

Ich habe mich deshalb entschlossen der TextBox einen KeyUpHandler hinzuzufügen der der Textbox die Möglichkeit gibt sich zu merken welcher Key losgelassen wurde. Das verwende ich nun in meinem SuggestOracle in der Methode requestSuggestions. Den gesamten Code der Implementierung kann man sich  aus meinen vorherigen Beiträgen zusammenreimen, hier die aktuell nötigen Änderungen damit das ganze klappt:

Hier die erweiterte TextBox die ich dann zum Erzeugen meiner SuggestBox verwende:

 private class MyTextBox extends TextBox {
  public int currentKeyUpStroke;
  private MyTextBox(Element element) {
   super(element);
   this.addKeyUpHandler(new KeyUpHandler() {
    @Override
    public void onKeyUp(KeyUpEvent event) {
     MyTextBox.this.currentKeyUpStroke = event.getNativeKeyCode();
    }
   });
  }
  public int getCurrentKeyUpStroke() {
   return currentKeyUpStroke;
  }
 }


Und hier die Stelle wo ich, bevor ich meine Services aufrufe, überprüfe ob nicht etwa ein Tab der Auslöser des ganzen war:

 private SuggestOracle getSuggestOracle() {
  final SuggestOracle so = new SuggestOracle() {

   @Override
   public void requestSuggestions(final Request request, final Callback callback) {

    if (request.getQuery().length() > 3
      && ((MyTextBox) RegeldatenTextInputCell.this.suggestBox.getTextBox()).getCurrentKeyUpStroke() != KeyCodes.KEY_TAB) {




Friday, 15 February 2013

GWT: SuggestBox in CellTable -> Auswahl per Maus klappt nicht.

GWT 2.5

In diesem Post habe ich eine SuggestBox mit einer Cell in einer CellTable verbunden, das klappte auch überraschend gut. Man konnte einen Vorschlag auswählen und der würde auch übernommen. Nur klappte das leider nur mit den Pfeiltasten und einer Enter Bestättigung, wollte man per Maus auswählen wurde der Wert einfach nicht übernommen.

Analog zu diesem Problem gibt es ein bisschen etwas im Netz zu finden, aber wirklich den Durchbruch brachte keiner der Tips:

codinginthetrenches.com: catching value change events from the gwt suggestbox
Google Code: google-web-toolkit: SuggestBox OnChange fired before suggestion text is set

Ich brachte das Teil endlich dazu die Maus Auswahl zu schlucken, aber nun nahm er die Pfeil/Enter Auswahl nicht mehr an, dazu die Codezeilen die in der onBrowserEvent Methode in meiner schon sehr erweiterten TextInputCell:


if (BrowserEvents.FOCUS.equals(eventType) && (isUserid || isUseridStrict || connectedUserid != null)) {
   TextBox textBox = new MyTextBox(getInputElement(parent));
   suggestBox = new MySuggestBox(getSuggestOracle(), textBox);
   suggestBox.onAttach();

   suggestBox.addSelectionHandler(new SelectionHandler<Suggestion>() {
    @Override
    public void onSelection(SelectionEvent<Suggestion> event) {
     final String selected = event.getSelectedItem().getReplacementString();
     ValueChangeEvent.fire(suggestBox, selected);
    }
   });
   suggestBox.addValueChangeHandler(new ValueChangeHandler<String>() {

    @Override
    public void onValueChange(ValueChangeEvent<String> event) {
     valueUpdater.update(event.getValue());
     suggestBox.setValue(event.getValue());
    }
   });
  }

Ich hatte soweit herausgefunden daß ich den valueUpdater benutzen musste damit die Table überhaupt mitbekommt daß ich etwas verändert habe, bei der Pfeil/Enter Auswahl kam das aber gar nicht gut an, aus welchem Grund auch immer nahm nun diese keine Auswahl mehr, wenn wer eine Erklärung dafür hat, ich würde mich freuen.

Mein größtes Problem war, wie unterscheide ich im Valuechangehandler ob ich durch einen Mausklick oder durch Pfeil/Enter updaten will? Schlussendlich hab ich dann irgendwann geschnallt dass wenn ich mit Pfeil/Enter in die onValueChange Methode rutsche den Value der suggestBox schon irgendwo gesetzt hatte, wenn also der Wert des Events und der in der suggestBox gleich sind brauche ich den valueUpdater nicht mehr zu bemühen, bzw. darf ihn gar nicht anwerfen, da sonst ja meine Pfeil/Enter Auswahl nicht mehr funktioniert:


suggestBox.addValueChangeHandler(new ValueChangeHandler<String>() {

    @Override
    public void onValueChange(ValueChangeEvent<String> event) {
     if (!suggestBox.getValue().equals(event.getValue())) {
      valueUpdater.update(event.getValue());
     }
     suggestBox.setValue(event.getValue());
    }
   });


Nachtrag 21.2.2013:

Leider funktioniert meine Lösung nicht für den IE8, darum hier Änderungen die mit dem aktuellen Chrome, FF und IE8 funktionieren, aber imho noch viel lausiger sind als die ursprünglich schon sehr dreckige Lösung:


suggestBox.addSelectionHandler(new SelectionHandler<Suggestion>() {
    @Override
    public void onSelection(SelectionEvent<Suggestion> event) {
     final String selected = event.getSelectedItem().getReplacementString();
     if (nativeEvent.getType().equals(BrowserEvents.CLICK)
       || !Window.Navigator.getUserAgent().contains("MSIE 8.0")) {
      ValueChangeEvent.fire(suggestBox, selected);
     }
    }
   });

   suggestBox.addValueChangeHandler(new ValueChangeHandler<String>() {

    @Override
    public void onValueChange(ValueChangeEvent<String> event) {
     if (!event.getValue().equals(suggestBox.getValue()) || Window.Navigator.getUserAgent().contains("MSIE 8.0")) {
      valueUpdater.update(event.getValue());
     }
    }
   });


nativeEvent ist einfach der Parameter der onBrowserEvent Methode.

Saturday, 15 December 2012

GWT: SuggestBox in einer CellTable

GWT 2.5

Hat man sich einmal entschlossen eine CellTable zu verwenden und stößt dann auf Anforderungen die die CellTable nicht von vornherein vorgesehen hat kann das sehr ärgerlich werden. Mir ging es so bei der Anforderung eine SuggestBox in der Table zu verwenden.
Schlußendlich stellte sich heraus daß das Ganze gar nicht so eine Zauberei ist, muß aber auch dazusagen, daß die Lösung noch nicht wirklich den Praxistest erlebt hat.

Meine Lösung besteht darin, einfach die TextInputCell zu extenden und so eine SuggestBox reinzuschummeln:


public class SuggestBoxTextInputCell extends TextInputCell {

 MySuggestBox suggestBox;

 private class MyTextBox extends TextBox {
  public MyTextBox(Element element) {
   super(element);
  }
 }

 private class MySuggestBox extends SuggestBox {
  public MySuggestBox(SuggestOracle suggestOracle, TextBox textBox) {
   super(suggestOracle, textBox);
  }

  @Override
  public void onAttach() {
   super.onAttach();
  }
 }

 public SuggestBoxTextInputCell() {
  super();
 }


 @Override
 public void onBrowserEvent(Context context, Element parent, String value, NativeEvent event,
   ValueUpdater<String> valueUpdater) {
  super.onBrowserEvent(context, parent, value, event, valueUpdater);
  String eventType = event.getType();
  if (BrowserEvents.FOCUS.equals(eventType)) {
   TextBox textBox = new MyTextBox(getInputElement(parent));
   suggestBox = new MySuggestBox(getSuggestOracle(), textBox);
   suggestBox.onAttach();
  }
 }

 private SuggestOracle getSuggestOracle() {
        //this does not work without implementation
        return null;
 }
}

Die Methode gestSuggestOracle muss natürlich noch implementiert werden um den Beispielcode lauffähig zu bekommen.
Links:
Google Groups Beitrag
Stackoverflow Beitrag zum Thema