Skip to content
This repository has been archived by the owner on Nov 15, 2019. It is now read-only.

Select returns first item as selected item before attach #344

Open
wildcart opened this issue Jan 7, 2018 · 2 comments
Open

Select returns first item as selected item before attach #344

wildcart opened this issue Jan 7, 2018 · 2 comments

Comments

@wildcart
Copy link

wildcart commented Jan 7, 2018

Hi,

I have a rather odd problem with Select returning the first item as selected
item (getSelectedItem / getValue) before it (its parent) is attached and
after being attached it returns null. The behaviour is the same
regardless if I add the option in the UI file or manually in the code.
'Unselecting' the option that I add manually doesn't help either.

If the Select is provided (@UiField(provided = true)) getSelectedItem
returns the first item even after the parents onAttach method was called.

The select and selected Selects (see code example below) show a
placeholder after the page has been loaded indicating that no item has been
selected, even then they return the first option before attached. The
provided Select does not have a placeholder and shows and returns the
first added option 'provided option 1' before and after being attached.

The behaviour of provided is somewhat expected, there's not placeholder so
the first option is shown and it seems logical that it is return as selected
item. The behaviour of the other two selects seems buggy(?) as I would expect
them to always return null / an empty value.

Is this behaviour expected or is this a bug?

The problem (for me) is that other code, in a project that I am involved with,
expects to always receive null / empty values when no item has been explicitly
selected by the user. As mentioned below: the state of the Selects is checked
by a function that is called from the start function of a GWT Activity.

This function is called before the Selects are attached if the the page is
reloaded (accessed directly) and after they are attached if switched to from a
different page in GWT application.

I can probably work around this dependency but it still seems odd that
Select::getSelectedItem returns different values whether the Select has
been attached or not.

best
Christian.

I have the following code in the UI file:

<!DOCTYPE ui:UiBinder SYSTEM "http://dl.google.com/gwt/DTD/xhtml.ent">
<ui:UiBinder xmlns:ui="urn:ui:com.google.gwt.uibinder"
    xmlns:b="urn:import:org.gwtbootstrap3.client.ui"
    xmlns:b.select="urn:import:org.gwtbootstrap3.extras.select.client.ui">
...
        <b.select:Select ui:field="provided" />
        <b.select:Select ui:field="select" title="select placeholder" />
        <b.select:Select ui:field="selected" title="selected placeholder">
            <b.select:Option text="option 1" />
            <b.select:Option text="option 2" />
            <b.select:Option text="option 3" />
        </b.select:Select>
...
</ui:UiBinder>

and the Java sources:

public final class SomeWidget extends Composite {
    interface SWBinder extends UiBinder<Widget, SomeWidget> {}
    private static SWBinder uiBinder = GWT.create(SWBinder.class);

    public SomeWiedget {

        this.provided = new Select();
        LOG.warning("-- provided: " + this.provided.getSelectedItem());
        this.initWidget(uiBinder.createAndBindUi(this));

        LOG.warning("++ provided:            " + this.provided.getSelectedItem());
        LOG.warning("++ select:              " + this.select.getSelectedItem());
        LOG.warning("++ selected:            " + this.selected.getSelectedItem());
        LOG.warning("++ selected.selected:   " + this.selected.getSelectedItem().getSelectElement().isSelected());
        LOG.warning("++ selected.default:    " + this.selected.getSelectedItem().getSelectElement().isDefaultSelected());

        final Option optProvided = new Option();
        optProvided.setText("provided option 1");
        optProvided.setSelected(false);
        optProvided.getSelectElement().setSelected(false);
        optProvided.getSelectElement().setDefaultSelected(false);
        this.provided.add(optProvided);
        LOG.warning("++++ provided:          " + this.provided.getSelectedItem());
        LOG.warning("++++ provided.selected: " + this.provided.getSelectedItem().getSelectElement().isSelected());
        LOG.warning("++++ provided.default:  " + this.provided.getSelectedItem().getSelectElement().isDefaultSelected());

        final Option optSelect = new Option();
        optSelect.setText("select option 1");
        optSelect.setSelected(false);
        optSelect.getSelectElement().setSelected(false);
        optSelect.getSelectElement().setDefaultSelected(false);
        this.select.add(optSelect);
        LOG.warning("++++ select:            " + this.select.getSelectedItem());
        LOG.warning("++++ select.selected:   " + this.select.getSelectedItem().getSelectElement().isSelected());
        LOG.warning("++++ select.default:    " + this.select.getSelectedItem().getSelectElement().isDefaultSelected());
    }

    @Override
    public void onAttach() {
        LOG.warning("before attach!");
        LOG.warning(">> provided:            " + this.provided.getSelectedItem());
        LOG.warning(">> select:              " + this.select.getSelectedItem());
        LOG.warning(">> selected:            " + this.selected.getSelectedItem());
        super.onAttach();
        LOG.warning("after attach!");
        LOG.warning("<< provided:            " + this.provided.getSelectedItem());
        LOG.warning("<< select:              " + this.select.getSelectedItem());
        LOG.warning("<< selected:            " + this.selected.getSelectedItem());
    }

    /** this function is called by an com.google.gwt.activity.shared.Activity's
      * start function. Important to notice it's called before onAttach if the
      * page was (re)loaded and after onAttach if the page is entered from
      * a different page of the GWT application later.
      */
    public void someFunction() {
        LOG.warning("== provided:            " + this.provided.getSelectedItem());
        LOG.warning("== select:              " + this.select.getSelectedItem());
        LOG.warning("== selected:            " + this.selected.getSelectedItem());
    }
}

The above code produces the following output if the page is (re)loaded, the
output marked with '==' will be printed after the last '<<' if the page is
accessed from another page of the GWT application after the application has
already been loaded (in the later case the returned values are null):

-- provided: null
++ provided:            null
++ select:              null
++ selected:            <option>option 1</option>
++ selected.selected:   true
++ selected.default:    false
++++ provided (val):    provided option 1
++++ provided:          <option>provided option 1</option>
++++ provided.selected: true
++++ provided.default:  false
++++ select (val):      select option 1
++++ select:            <option>select option 1</option>
++++ select.selected:   true
++++ select.default:    false
== provided:            <option>provided option 1</option>
== select:              <option>select option 1</option>
== selected:            <option>option 1</option>
before attach!
>> provided:            <option>provided option 1</option>
>> provided (val):      provided option 1
>> select:              <option>select option 1</option>
>> select (val):        select option 1
>> selected:            <option>option 1</option>
>> selected (val):      option 1
after attach!
<< provided:            <option>provided option 1</option>
<< provided (val):      provided option 1
<< select:              null
<< select (val):
<< selected:            null
<< selected (val):
@sjardine
Copy link
Member

sjardine commented Jan 8, 2018

I will have to do some more investigation but the main problem here is that this component is just a wrapper for the Bootstrap Select project. How it behaves before it is attached and after is mostly dependent on the underlying component.

@wildcart
Copy link
Author

wildcart commented Jan 8, 2018

Thanks for the quick response.

I've seen that it is a wrapper while tracking the problem why my code behaved unexpectedly :)

What I have noticed is that the code in Select::getValue has a switch checking whether the Select is attached or not. If it is attached it uses $wnd.jQuery(e).selectpicker('val'); to return the selected value, else it iterates over the map of 'items' returning the fist isSelected option. Seeing this code I would have expected that it must be sufficient to explicitly call setSelected(false) before adding an option. This, however, is not the case :(

The implementation of Select::getSelectedItem does not make this distinction and always iterates over the map.

While writing my response I just now realised, that I only printed the output of getSelecteditem and I ignored getValue, if I remember correctly I also checked getValue but never added it to the isolated test case I used above. Well here's the output of getValue taken from the 'full' application which pretty much show the same behaviour:

value:   Afghanistan
attached!
value:  

Thanks for checking this.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants