You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@wicket.apache.org by ChambreNoire <aw...@tentelemed.com> on 2014/02/13 17:05:04 UTC

Hybrid palette with DropDownChoice and ListView

Hello,

I'd like to create a hybrid 'palette'. First there's a DropDownChoice with
an 'Add' link and next to this a vertical list of selected items, each with
a 'remove' link. Of course, adding an item removes it from the
DropDownChoice and adds it to the list and vice-versa for item 'removal'. 

I have already started but I fear that this is probably going to be fairly
complicated as it involves using ListViews in a form and DropDownChoice
customisation so any pointers to get me going would be most appreciated.
I'll post some code once I have something vaguely functional!

Thanks,

Chambre

--
View this message in context: http://apache-wicket.1842946.n4.nabble.com/Hybrid-palette-with-DropDownChoice-and-ListView-tp4664445.html
Sent from the Users forum mailing list archive at Nabble.com.

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@wicket.apache.org
For additional commands, e-mail: users-help@wicket.apache.org


Re: Hybrid palette with DropDownChoice and ListView

Posted by ChambreNoire <aw...@tentelemed.com>.
Great, I'm still getting NonUniqueObjectExceptions when I save. Back to the
drawing board. *sigh*

--
View this message in context: http://apache-wicket.1842946.n4.nabble.com/Hybrid-palette-with-DropDownChoice-and-ListView-tp4664445p4664562.html
Sent from the Users forum mailing list archive at Nabble.com.

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@wicket.apache.org
For additional commands, e-mail: users-help@wicket.apache.org


Re: Hybrid palette with DropDownChoice and ListView

Posted by ChambreNoire <aw...@tentelemed.com>.
OK so this is what I have so far. Seems to work OK.

public class DropDownPalette<T> extends FormComponentPanel {

    private static final String UNSELECTED_ID = "unselected";
    private static final String SELECT_ACTION_ID = "select";
    private static final String SELECTED_ID = "selected";
    private static final String SELECTED_NAME_ID = "selected_name";
    private static final String UNSELECT_ID = "unselect";

    private IModel choicesModel;
    private IChoiceRenderer choiceRenderer;

    private transient List<T> selectedChoices;
    private transient List<T> unselectedChoices;

    private String[] ids;

    public DropDownPalette(String id, IModel model, IModel choicesModel,
IChoiceRenderer choiceRenderer) {
        super(id, model);

        setOutputMarkupId(true);

        this.choicesModel = choicesModel;
        this.choiceRenderer = choiceRenderer;

        IModel unselectedChoices = new LoadableDetachableModel() {

            @Override
            protected Object load() {

                return getUnselectedChoices();
            }
        };

        DropDownChoice choice = new DropDownChoice(UNSELECTED_ID, new
Model(), unselectedChoices, choiceRenderer);

        choice.add(new OnChangeAjaxBehavior() {

            @Override
            protected void onUpdate(AjaxRequestTarget target) {

                target.addComponent(DropDownPalette.this);
            }
        });

        add(choice);

        add(new AjaxLink(SELECT_ACTION_ID) {

            @Override
            public void onClick(AjaxRequestTarget target) {

                getModelCollection().add(getCurrentChoice());

                setCurrentChoice(null);
                initIds();

                onItemSelected(target);

                target.addComponent(DropDownPalette.this);
            }

            @SuppressWarnings("unchecked")
            private T getCurrentChoice() {
                return (T) getParent().get(UNSELECTED_ID).getModelObject();
            }

            private void setCurrentChoice(T choice) {
                getParent().get(UNSELECTED_ID).setModelObject(choice);
            }

            @Override
            protected void onBeforeRender() {

                setVisibilityAllowed(getCurrentChoice() != null);
                super.onBeforeRender();
            }

            @Override
            protected boolean callOnBeforeRenderIfNotVisible() {
                return true;
            }
        });

        IModel selectedChoices = new AbstractReadOnlyModel() {

            @Override
            public Object getObject() {
                return getSelectedChoices();
            }
        };

        add(new ListView(SELECTED_ID, selectedChoices) {

            @Override
            protected void populateItem(ListItem item) {

                Object displayValue =
getChoiceRenderer().getDisplayValue(item.getModelObject());

                item.add(new Label(SELECTED_NAME_ID, new
Model(String.valueOf(displayValue))));

                item.add(new AjaxLink(UNSELECT_ID) {

                    @Override
                    @SuppressWarnings("SuspiciousMethodCalls")
                    public void onClick(AjaxRequestTarget target) {

                       
getModelCollection().remove(getParent().getModelObject());

                        flushSelectedChoices(); // in order to reload the
choices

                        onItemUnselected(target);

                        target.addComponent(DropDownPalette.this);
                    }
                });
            }
        });
    }

    protected void onItemUnselected(AjaxRequestTarget target) {}

    protected void onItemSelected(AjaxRequestTarget target) {}

    @Override
    protected void convertInput() {
        setConvertedInput(getSelectedChoices());
    }

    protected void onBeforeRender() {

        if (!getForm().hasError()) {
            initIds();
        }
        super.onBeforeRender();
    }

    @SuppressWarnings("unchecked")
    public List<T> getSelectedChoices() {

        if (selectedChoices == null) {

            IChoiceRenderer renderer = getChoiceRenderer();

            if (ids.length == 0) {
                return Collections.EMPTY_LIST;
            }

            selectedChoices = new ArrayList<T>(ids.length);

            for (String id : ids) {

                for (T choice : getChoices()) {

                    if (renderer.getIdValue(choice, 0).equals(id)) {

                        selectedChoices.add(choice);
                        break;
                    }
                }
            }
        }
        return selectedChoices;
    }

    @SuppressWarnings("unchecked")
    public List<T> getUnselectedChoices() {

        if (unselectedChoices == null) {

            Collection<T> choices = getChoices();

            if (choices.size() - ids.length == 0) {
                return Collections.EMPTY_LIST;
            }

            unselectedChoices = new ArrayList<T>(Math.max(1, choices.size()
- ids.length));

            for (T choice : choices) {

                final String choiceId =
getChoiceRenderer().getIdValue(choice, 0);

                boolean selected = false;

                for (String id : ids) {

                    if (id.equals(choiceId)) {
                        selected = true;
                        break;
                    }
                }
                if (!selected) {
                    unselectedChoices.add(choice);
                }
            }
        }
        return unselectedChoices;
    }

    private void flushSelectedChoices() {
        selectedChoices = null;
    }

    private void initIds() {

        IChoiceRenderer renderer = getChoiceRenderer();

        Iterator selection = getModelCollection().iterator();

        ids = new String[getModelCollection().size()];

        int i = 0;
        while (selection.hasNext()) {

            ids[i] = renderer.getIdValue(selection.next(), i++);
        }
    }

    @SuppressWarnings("unchecked")
    public Collection<T> getChoices() {
        return (Collection<T>) choicesModel.getObject();
    }

    @SuppressWarnings("unchecked")
    public Collection<T> getModelCollection() {
        return (Collection<T>) getModelObject();
    }

    public IChoiceRenderer getChoiceRenderer() {
        return this.choiceRenderer;
    }

    @Override
    protected void onDetach() {

        selectedChoices = null;
        unselectedChoices = null;

        super.onDetach();
    }
}

--
View this message in context: http://apache-wicket.1842946.n4.nabble.com/Hybrid-palette-with-DropDownChoice-and-ListView-tp4664445p4664450.html
Sent from the Users forum mailing list archive at Nabble.com.

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@wicket.apache.org
For additional commands, e-mail: users-help@wicket.apache.org


Re: Hybrid palette with DropDownChoice and ListView

Posted by ChambreNoire <aw...@tentelemed.com>.
Thanks for the suggestions. Regrettably the spec requires a vertical list of
labels and specifically not a multi choice list as used in the extensions
Palette component otherwise yes it would be trivial to make the right hand
side a one row drop down as you mention...

--
View this message in context: http://apache-wicket.1842946.n4.nabble.com/Hybrid-palette-with-DropDownChoice-and-ListView-tp4664445p4664448.html
Sent from the Users forum mailing list archive at Nabble.com.

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@wicket.apache.org
For additional commands, e-mail: users-help@wicket.apache.org


Re: Hybrid palette with DropDownChoice and ListView

Posted by Paul Bors <pa...@bors.ws>.
Btw, Select2 demos are at:
http://ivaynberg.github.io/select2/

Its Wicket integration at:
https://github.com/ivaynberg/select2

That's Igor's baby (you might have seen Igor's name in Wicket's API
JavaDocs :)


On Thu, Feb 13, 2014 at 11:34 AM, Paul Bors <pa...@bors.ws> wrote:

> I don't think you need to go nuts and worry much about a ListView. Use a
> Select2 instead of the drop-down and have a custom panel instead of the
> plain old option. You can place an Add button or something or better yet,
> check boxes and then you won't need the second list.
>
> Suppose you do stick to old HTML components like a DropDown and a
> ListView. First off, get off the list view and use a multiple Select.
> Take a look at how the wicket pallet is done at:
>
> http://www.wicket-library.com/wicket-examples/compref/wicket/bookmarkable/org.apache.wicket.examples.compref.PalettePage
>
> All you would have to do is change the left available multi select with
> your drop down.
>
>
> Now, I would recommend using jQuery UI's widgets since they are easier to
> use and more fun to work with (both for the developer and the application
> user):
> http://jqueryui.com/demos/
>
> Have fun!
>
> On Thu, Feb 13, 2014 at 11:05 AM, ChambreNoire <aw...@tentelemed.com> wrote:
>
>> Hello,
>>
>> I'd like to create a hybrid 'palette'. First there's a DropDownChoice with
>> an 'Add' link and next to this a vertical list of selected items, each
>> with
>> a 'remove' link. Of course, adding an item removes it from the
>> DropDownChoice and adds it to the list and vice-versa for item 'removal'.
>>
>> I have already started but I fear that this is probably going to be fairly
>> complicated as it involves using ListViews in a form and DropDownChoice
>> customisation so any pointers to get me going would be most appreciated.
>> I'll post some code once I have something vaguely functional!
>>
>> Thanks,
>>
>> Chambre
>>
>> --
>> View this message in context:
>> http://apache-wicket.1842946.n4.nabble.com/Hybrid-palette-with-DropDownChoice-and-ListView-tp4664445.html
>> Sent from the Users forum mailing list archive at Nabble.com.
>>
>> ---------------------------------------------------------------------
>> To unsubscribe, e-mail: users-unsubscribe@wicket.apache.org
>> For additional commands, e-mail: users-help@wicket.apache.org
>>
>>
>

Re: Hybrid palette with DropDownChoice and ListView

Posted by Paul Bors <pa...@bors.ws>.
I don't think you need to go nuts and worry much about a ListView. Use a
Select2 instead of the drop-down and have a custom panel instead of the
plain old option. You can place an Add button or something or better yet,
check boxes and then you won't need the second list.

Suppose you do stick to old HTML components like a DropDown and a ListView.
First off, get off the list view and use a multiple Select.
Take a look at how the wicket pallet is done at:
http://www.wicket-library.com/wicket-examples/compref/wicket/bookmarkable/org.apache.wicket.examples.compref.PalettePage

All you would have to do is change the left available multi select with
your drop down.


Now, I would recommend using jQuery UI's widgets since they are easier to
use and more fun to work with (both for the developer and the application
user):
http://jqueryui.com/demos/

Have fun!

On Thu, Feb 13, 2014 at 11:05 AM, ChambreNoire <aw...@tentelemed.com> wrote:

> Hello,
>
> I'd like to create a hybrid 'palette'. First there's a DropDownChoice with
> an 'Add' link and next to this a vertical list of selected items, each with
> a 'remove' link. Of course, adding an item removes it from the
> DropDownChoice and adds it to the list and vice-versa for item 'removal'.
>
> I have already started but I fear that this is probably going to be fairly
> complicated as it involves using ListViews in a form and DropDownChoice
> customisation so any pointers to get me going would be most appreciated.
> I'll post some code once I have something vaguely functional!
>
> Thanks,
>
> Chambre
>
> --
> View this message in context:
> http://apache-wicket.1842946.n4.nabble.com/Hybrid-palette-with-DropDownChoice-and-ListView-tp4664445.html
> Sent from the Users forum mailing list archive at Nabble.com.
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: users-unsubscribe@wicket.apache.org
> For additional commands, e-mail: users-help@wicket.apache.org
>
>