Announcement

Collapse
No announcement yet.
X
  • Filter
  • Time
Clear All
new posts

    Is it possible to manually move caret in a FormItem?

    In our app, we have a function where forms enter and exit "editmode" i.e. it can be seen when the form starts to be editable. When that happens we put focus on one specific item in the form.

    All this works, but if the formitem is not empty (i.e we're editing rather then creating a new item), the caret appears at the end of the text. It would be better if the caret was at the start of the formitem (a dateitem). So that you can just start typing.

    Is this at all possible?

    #2
    Yes, you can call setSelectionRange(0, 0) on your item

    Comment


      #3
      Ah - i did not find this because it's not in FormItem. This means that i somehow have to check manually what type it is and cast it to the respective class if i want to change it. Would have loved for it to be in FormItem instead and not do anything for SelectItems :)

      Anyway - thanks!

      Comment


        #4
        Hmm. I can't get this call to have any effect. I made a small method i call whenever i put focus on a formitem:

        Code:
        private void checkSelectBeginning(FormItem item){
                if(item instanceof DateItem){
                    GWT.log("is dateitem, setting selectionrange to 0,0 : " + ((DateItem) item).getUseTextField());
                    ((DateItem)item).setSelectionRange(0,0);
                }else if(item instanceof TextItem){
                    ((TextItem)item).setSelectionRange(0,0);
                    GWT.log("is textitem, setting selectionrange to 0,0" + ((DateItem) item).getUseTextField());
                }
            }
        I do get the printout:
        is dateitem, setting selectionrange to 0,0 : true
        So the object seems to be valid? However, the caret stays at the end of the formitem. Any suggestions?

        Comment


          #5
          This could be an issue with timing, perhaps due to how/where you're putting focus in the item.

          We would expect setSelectionRange() to work if you called it from an EditorEnter handler, which runs only when focus enters the editor itself.

          Comment


            #6
            Hi, thanks for response. I've tried focushandlers, and couldn't that get to work either.

            I made a small testcase below, perhaps you can see something obvious? As you can see i've tried various different approaches to no avail. What seems to happen is that the caret does move to the beginning, but then immediately jumps back to the end.


            My desired outcome is: When the form goes into editmode, put focus on a specific item and put caret in the beginning so that the user can start overwriting the current value. by typing without having to do anything first.


            Code:
            public void onModuleLoad() {
                    final DynamicForm form = new DynamicForm();
                    form.setNumCols(3);
                    form.setWidth(300);
            
                    TextItem firstName = new TextItem("name");
                    firstName.setTitle("Name");
                    firstName.setWrapTitle(false);
            
                    DateTimeItem dateTimeItem = new DateTimeItem("time");
                    dateTimeItem.setAlign(Alignment.LEFT);
                    dateTimeItem.setTextAlign(Alignment.LEFT);
                    dateTimeItem.setUseMask(true);
                    dateTimeItem.setTitle("Time");
                    dateTimeItem.setWrapTitle(false);
            
                    form.setCanEdit(false);
                    form.setFields(firstName, dateTimeItem);
            
            
                    Button button = new Button("Do test");
                    button.addClickHandler(clickEvent -> {
                        form.setCanEdit(true);
                        form.editRecord(createRecord());
                        doTheFocusThing(dateTimeItem);
                    });
            
            
                    //does not work either, not with form focushandler, not with formitem focushandler
                    /*dateTimeItem.addFocusHandler(focusChangedEvent -> {
                        GWT.log("FOCUS CHANGED HANDLER");
                        doTheFocusThing(dateTimeItem);
                    }); */
            
                    VLayout layout = new VLayout();
                    layout.setPadding(30);
                    layout.setMembersMargin(15);
                    layout.addMember(button);
                    layout.addMember(form);
                    layout.draw();
                    button.focus();
                }
            
                private void doTheFocusThing(FormItem item){
                    GWT.log("DOING FOCUS THING");
                    item.focusInItem();
                    checkSelectBeginning(item);
                }
            
                private void checkSelectBeginning(FormItem item) {
                    if (item instanceof DateItem) {
                        GWT.log("is dateitem, setting selectionrange to 0,0 : " + ((DateItem) item).getUseTextField());
                        ((DateItem) item).setSelectionRange(0, 0);
                    } else if (item instanceof TextItem) {
                        ((TextItem) item).setSelectionRange(0, 0);
                        GWT.log("is textitem, setting selectionrange to 0,0" + ((DateItem) item).getUseTextField());
                    }
                }

            Comment


              #7
              Hi Mathias
              The problem here is that your setSelectionRange call is "fighting with" some framework logic for items with useMask set to true, whereby on focus we automatically put the caret after the last populated character in the mask.

              We agree that this framework logic shouldn't be preventing you explicitly setting the selection range in this way and have a developer assigned to take a look at this as a possible bug. You could work around it by putting the "setSelectionRange()" call in a timer so it executes asynchronously after focus completes:
              Code:
              ...
                Timer t = new Timer() {
                  @Override
                  public void run() {
                    ((DateItem)item).setSelectionRange(0,0);
                  }
                };
              
                t.schedule(100);
              ...
              However it seems like the "selectOnFocus" attribute may actually be a better option for you. If you call setSelectOnFocus(true) for your item, it should ensure that even for items with useMask:true, the default behavior on focus is to select the whole value of the item. This would allow the user to start typing and overwrite the existing value without any problems.

              * If this setting doesn't behave as described for you, let us know exactly which version of SmartGWT you're using, and show us the code from your modified attempt.

              Thanks
              Isomorphic Software

              Comment


                #8
                Hi, thanks for getting back. I am currently using 13.0-p20220208.

                Yeah, that does indeed sound like a bug to me. Would be fantastic if you took a look at it.



                Regarding "selectonfocus()", i tried amending my testcase so that i call setselectonfocus on the dataitem (code below).

                adding selectonfocus has no effect on the formitem. All text is not selected when i click on the button, and the caret moves as before.

                ( If i call "selectonclick", all text in the field is selected when i click on it with the mouse, so that works. )


                So, i can't see that this helps my use case, unfortunately. It's not exactly what i'd like, anyway. I think it would be better if the old value is seen while typing. If all text is selected, the field will be emptied as soon as the user clicks the first key.



                Code:
                public void onModuleLoad() {
                        final DynamicForm form = new DynamicForm();
                        form.setNumCols(3);
                        form.setWidth(300);
                
                        TextItem firstName = new TextItem("name");
                        firstName.setTitle("Name");
                        firstName.setWrapTitle(false);
                
                        DateTimeItem dateTimeItem = new DateTimeItem("time");
                        dateTimeItem.setAlign(Alignment.LEFT);
                        dateTimeItem.setTextAlign(Alignment.LEFT);
                        dateTimeItem.setUseMask(true);
                        dateTimeItem.setTitle("Time");
                        dateTimeItem.setWrapTitle(false);
                
                //----> NEW ROWS HERE
                        dateTimeItem.setSelectOnFocus(true); //no visible effect from what i can see
                        //dateTimeItem.setSelectOnClick(true); this makes the form text be "all selected" when clicked on with mouse
                
                        form.setCanEdit(false);
                        form.setFields(firstName, dateTimeItem);
                
                
                        Button button = new Button("Do test");
                        button.addClickHandler(clickEvent -> {
                            form.setCanEdit(true);
                            form.editRecord(createRecord());
                            doTheFocusThing(dateTimeItem);
                        });
                
                
                        //does not work either, not with form focushandler, not with formitem focushandler
                        /*dateTimeItem.addFocusHandler(focusChangedEvent -> {
                            GWT.log("FOCUS CHANGED HANDLER");
                            doTheFocusThing(dateTimeItem);
                        }); */
                
                        VLayout layout = new VLayout();
                        layout.setPadding(30);
                        layout.setMembersMargin(15);
                        layout.addMember(button);
                        layout.addMember(form);
                        layout.draw();
                        button.focus();
                    }
                
                    private void doTheFocusThing(FormItem item){
                        GWT.log("DOING FOCUS THING");
                        item.focusInItem();
                        checkSelectBeginning(item);
                    }
                
                    private void checkSelectBeginning(FormItem item) {
                        if (item instanceof DateItem) {
                            GWT.log("is dateitem, setting selectionrange to 0,0 : " + ((DateItem) item).getUseTextField());
                            ((DateItem) item).setSelectionRange(0, 0);
                        } else if (item instanceof TextItem) {
                            ((TextItem) item).setSelectionRange(0, 0);
                            GWT.log("is textitem, setting selectionrange to 0,0" + ((DateItem) item).getUseTextField());
                        }
                    }

                Comment


                  #9
                  Hey just following up on this, did anybody have time to give it any thought? As it stands it's unusable to us - i tried the "timer" workaround, but it looks janky and i think it's difficult to set the timer value to a value so that it's reliable. Would be great if this was fixed at some point.

                  Comment


                    #10
                    HI guys, just pinging to see if anyone has had the time to look at this issue. It looks really janky right now so we've had to turn it off completely.

                    Comment


                      #11
                      Hello again, just pinging again to see if there are any plans to look into this.

                      Comment


                        #12
                        Hi, I guess it's that time of year again. Did the developer assigned ever get a chance to look at this?

                        Comment


                          #13
                          Hi Mathias
                          This issue should now be resolved in 13.0 and 13.1 builds dated Feb 28 or later
                          Please let us know if it persists for you and we apologize for the long delay in getting it resolved

                          Regards
                          Isomorphic Software

                          Comment


                            #14
                            Yeah well, better late than never as they say :) It works like a charm.

                            Edit: investigating further, I have a question. I do this when the entire form gets focus, that is, I select the form item and set the selection range.

                            However, if I want this to happen when the user tabs through the form, I have to manually add a focus handler and set the selection range when the item gets focus right? that's the best way?


                            EDIT AGAIN:

                            I have another problem getting this to work:

                            My plan was to add a focus handler, and when the onFocus is called on the datetimeitem, set selection range. The problem is that the method gets called, and then again when the user tabs to the small calendar select icon. In both cases isFocused() returns true.

                            I don't want to call setSelectionRange when the icon gets focus, because that makes the caret jump back to the text field right away...

                            Not sure how to solve this - I can't have an internal boolean "focusalreadycalled" because the handler doesn't get called when the item loses focus, so I can't reset the boolean.

                            Basically, I need to know if it's the text item, or the icon that is given focus in the event.

                            Thankful for input.
                            Last edited by mathias; 1 Mar 2024, 01:42.

                            Comment


                              #15
                              For what it's worth, with this one, you are the record-holder for verified but unresolved bugs.

                              We are very aggressive with bugs in general!

                              Our philosophy is that one bug report means 10 people hit it! This one just slipped through...

                              Comment

                              Working...
                              X