Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Form Dropdowns do not show ... (empty selection) once something is selected #418

Closed
PhilippGrashoff opened this issue Mar 28, 2018 · 9 comments
Assignees
Labels

Comments

@PhilippGrashoff
Copy link
Collaborator

If a Form is associated with a model, it displays hasOne References as Dropdown.

When no value for this dropdown is set, it shows an empty selection (... placeholder).
As soon as a value is selected, this option disappears. So its no possible to un-select this hasOne Reference any more.
The ... option should only disappear when the field is set to required = true

Empty selection available
empty_selection_there

And gone after something was selected
empty_selection_gone

@DarkSide666
Copy link
Member

DarkSide666 commented Mar 28, 2018

Here is fix for that which I use in one project for quite some time:

/**
 * Dropdown form field for single select by Imants.
 * Uses Semantic-UI dropdown.
 *
 * @TODO Semantic UI don't allow to unselect value :(
 *       https://github.com/Semantic-Org/Semantic-UI/issues/2072
 * Workaround #1: https://jsfiddle.net/xu4fv5n0/2/ - see slightly improved version below
 * Workaround #2: https://jsfiddle.net/hghkwkgv/6/
 */
class Form_Field_Semantic_DropdownSingle extends Form_Field_Dropdown
{
    public function getInput($attr=[])
    {
        $this->setProperty('class','ui search selection dropdown');
        $this->setProperty('name', $this->name);
        $this->js(true)->_v3()->dropdown([
            'placeholder' => 'auto',
            'forceSelection' => false, // if you find tab annoying, then put false here
            //'allowTab' => false,
            'match' => 'text',
            'fullTextSearch' => 'exact',

            // workaround for semantic ui issue mentioned above
            'onChange' => $this->js(null,'function(value) {
                var target = jQuery(this).dropdown();
                if (value!="") {
                    target.find(".dropdown.icon").removeClass("dropdown").addClass("delete").on("click", function() {
                        target.dropdown("clear");
                        jQuery(this).removeClass("delete").addClass("dropdown");
                        return false;
                    });
                }
            }'),
        ]);

        // workaround to force onChange event on initialization
        $this->js(true)->_v3()
            // set active selection
            ->closest('.ui.selection')->find('.item.active')->addClass('qwerty')->end()
            ->dropdown('clear')
            ->find('.qwerty')->removeClass('qwerty')
            ->trigger('click')
            // remove focus from field
            ->closest('.ui.selection')->find('input.search')->blur()
            ;

        return parent::getInput($attr);
    }

    public function getOption($value)
    {
        return $this->getTag('option', [
            'value'     => $value,
            'selected'  => $this->value && $value == $this->value,
        ]);
    }
}

@romaninsh
Copy link
Member

Shouldn't it be \atk4\ui\FormField\Dropdown instead of Form_Field_Dropdown ?

@DarkSide666
Copy link
Member

It's for smbo project and extends older toolkit (amodules3) Form_Field_Dropdown, but with some modifications this trick should work on new ui field too.

@DarkSide666
Copy link
Member

DarkSide666 commented Mar 28, 2018

And this is for multiple value select dropdown.

/**
 * Dropdown form field for multi select by Imants.
 * Uses Semantic-UI dropdown.
 */
class Form_Field_Semantic_DropdownMulti extends Form_Field_Dropdown
{
    public function getInput($attr=[])
    {
        $this->setProperty('multiple',true);
        $this->setProperty('class','ui search selection dropdown');
        $this->setProperty('name', $this->name.'[]');
        $this->js(true)->_v3()->dropdown([
            'placeholder' => 'auto',
            'forceSelection' => false, // if you find tab annoying, then put false here
            //'allowTab' => false,
            'match' => 'text',
            'fullTextSearch' => 'exact',
        ]);

        return parent::getInput($attr);
    }

    public function getOption($value)
    {
        return $this->getTag('option', [
            'value'     => $value,
            'selected'  => $this->value && in_array($value, $this->value),
        ]);
    }
}

No need for workaround hacks in this case.

@PhilippGrashoff
Copy link
Collaborator Author

Had a quick look into it, in the HTML code the empty selection is always there, so its definitely on the JS side. forceSelection option seems to be the one. will continue later.

@PhilippGrashoff
Copy link
Collaborator Author

Has nothing to do with forceSelection :) Here is the according sematic UI issue:
Semantic-Org/Semantic-UI#2072

There seems to be a proper solution, lets hope it gets into the next release.
Until then, some more or less ugly workarounds seem to be the only option.
@DarkSide666 couldn't make your workaround working in newest ATK release.

@DarkSide666
Copy link
Member

DarkSide666 commented Apr 10, 2018

Hmmm...
Semantic-Org/Semantic-UI#2072 (comment)

I don't think Semantic will fix anything. More that 2 years have passed and still no official fix for this.

@ibelar
Copy link
Contributor

ibelar commented Apr 10, 2018

@PhilippGrashoff

Try this to see if this work for you.

  • Create a new Dropdown field class like below.
  • This one add the placeholder option in dropdown module.

Then you can use this like:

$m->hasOne('country1', [new Country(), 'ui' => ['form' => [new MyDropDown()]]]);
class MyDropDown extends atk4\ui\FormField\Input
{
    public $rows = 2;

    public $values = [];

    public $empty = '...';

    public function init()
    {
        parent::init();
        $this->jsInput(true)->dropdown(['placeholder' => 'value']);
    }

    /**
     * returns <input .../> tag.
     */
    public function getInput()
    {
        $value = isset($this->field) ? $this->app->ui_persistence->typecastSaveField($this->field, $this->field->get()) : $this->content ?: '';

        $options = [];
        if ($this->empty) {
            $item = ['option', 'value' => '', $this->empty];
            $options[] = $item;
        }

        if (isset($this->model)) {
            foreach ($this->model as $key => $row) {
                $title = $row->getTitle();

                $item = ['option', 'value' => (string) $key, $title];
                if ($value == $key) {
                    $item['selected'] = true;
                }
                $options[] = $item;
            }
        } else {
            foreach ($this->values as $key => $val) {
                $item = ['option', 'value' => (string) $key, $val];
                if ($value == $key) {
                    $item['selected'] = true;
                }
                $options[] = $item;
            }
        }

        return $this->app->getTag('select', [
            'class'       => 'fluid search selection',
            'name'        => $this->short_name,
            'type'        => $this->inputType,
            'rows'        => $this->rows,
            'placeholder' => $this->placeholder,
            'id'          => $this->id.'_input',
        ], [[$options]]
        //
        );
        //return '<input name="'.$this->short_name.'" type="'.$this->inputType.'" placeholder="'.$this->placeholder.'" id="'.$this->id.'_input"/>';
    }
}

If this work then we can add a way to pass options to regular Dropdown input.

When I use this, then the empty option become available after selecting a value.

dropdown-with-placholder-value

@ghost ghost added the in progress label Apr 10, 2018
@PhilippGrashoff
Copy link
Collaborator Author

@ibelar you definitely are the JS god in here, though your fix has nothing to do with magically altering some JS or so - it just works :) :) :) Just adding ANY placeholder works.
I just commited a simple solution which works flawlessly here: #431

@ghost ghost removed the in progress label Apr 12, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Development

No branches or pull requests

4 participants