Laravel-Backpack / addons

A place for the Backpack community to talk about possible Backpack add-ons.
5 stars 2 forks source link

[4.1][Package / Custom Field] Field type text_suggestions_from_array aka Autocomplete #15

Closed chriscalip closed 1 year ago

chriscalip commented 6 years ago

Who wants it? Can we have it?

Autocomplete from array, text_suggestions_from_array datalist-default flexdatalist

Difference between select2 and autocomplete datalist? Think of it as the difference between a requirement and a suggestion. For the select element, the user is required to select one of the options you've given. For the datalist element, it is suggested that the user select one of the options you've given, but he can actually enter anything he wants in the input.

~~All features found in https://laravel-backpack.readme.io/docs/crud-fields#section-select_from_array with an additional feature of "or_other"~~ Roughly same feature: https://www.drupal.org/project/select_or_other

chriscalip commented 6 years ago

In a position to deliver this feature request. So at the essence of this feature request is the idea of helping users to answer a question with suggestions.

Now one way to go about this is to make a "pick an option or other" flow. select-or-other-pic This can be a pain to deliver because it merges 2 form fields: checkboxes, and a textbox into one.

Another way to go about this is just a textbox with suggestions http://blog.teamtreehouse.com/creating-autocomplete-dropdowns-datalist-element https://stackoverflow.com/questions/6865943/html-form-select-option-vs-datalist-option datalist-default

chriscalip commented 6 years ago

Well I am down to picking 2 libraries; each with its advantages and disadvantages.

https://github.com/leaverou/awesomplete/ https://github.com/pawelczak/EasyAutocomplete

chriscalip commented 6 years ago

Text Suggestions libraries capable of doing multiple values. Both libraries uses convention of comma separated values to denote multiple values.

http://projects.sergiodinislopes.pt/flexdatalist/ https://github.com/leaverou/awesomplete/

Flextdatalist is heavier (requires jquery!) but has better visual feedback on selections flexdatalist Awesomplete is lighter but less visual feedback on selections, eg. Textbox field values are comma separated. awesomplete

mamarmite commented 6 years ago

I made a suggestion in PR Laravel-Backpack/CRUD#1257 with a toggling functionnality. It's still very WIP, but you can start with that by making a toggle option on the other value and managing the save process after validation.

Any suggestions, fixes or improvements are very welcome.

chriscalip commented 6 years ago

@mamarmite Right, interesting feature. the difference of this feature request is that select2 makes options required entry values. This feature allows entries outside the options. For more details see: https://stackoverflow.com/questions/6865943/html-form-select-option-vs-datalist-option

Errata: I switched from suggestion checkboxes or other to textfield autocomplete suggestions.

indra1 commented 6 years ago

You know you can add your own custom fields in backpack, right? I don't really see the need for this tbh

chriscalip commented 6 years ago

@indra1 Yes, I've already added my custom fields. it works; I was just making a patch for it. Close this issue if you don't want a pull request.

chriscalip commented 6 years ago

Custom code with the limitations of the available autocomplete js libraries are not ready for the rigors of contributing back. I am closing this issue.

If anyone wants to bring this back.. here were the roadblocks.

http://projects.sergiodinislopes.pt/flexdatalist/ had better ux but has critical bug: https://github.com/sergiodlopes/jquery-flexdatalist/issues/118 This prevents multiple values feature for this autocomplete js library.

https://github.com/LeaVerou/awesomplete/issues/14184 has ok ux for multiple values.. but has a feature request that just not moving. https://github.com/LeaVerou/awesomplete/issues/14184 This prevents the nice tagging style on multiple values feature.

chriscalip commented 6 years ago

Anyone interested on using this crud field type. Here's a basic draft. text_suggestions_from_array using js library http://leaverou.github.io/awesomplete/

resources/views/vendor/backpack/crud/fields/text_suggestions_from_array.blade.php

<!-- text_suggestions_from_array -->
<div @include('crud::inc.field_wrapper_attributes') >
    <label>{!! $field['label'] !!}</label>
    <br />
    <input
        type="text"
        name="{{ $field['name'] }}"
        data-list="#{{ $field['name'] }}-datalist"
        value="{{ old($field['name']) ? old($field['name']) : (isset($field['value']) ? $field['value'] : (isset($field['default']) ? $field['default'] : '' )) }}"
        @include('crud::inc.field_attributes', ['default_class' =>  'form-control awesomplete'])
        @if (isset($field['allows_multiple']) && $field['allows_multiple']==true)data-multiple @endif
    >
    <ul
        id="{{ $field['name'] }}-datalist"
        style="display:none">

        @if (count($field['options']))
            @foreach ($field['options'] as $key => $value)
                @if((old($field['name']) && ($key == old($field['name']) || is_array(old($field['name'])) && in_array($key, old($field['name'])))) || (is_null(old($field['name'])) && isset($field['value']) && ($key == $field['value'] || (is_array($field['value']) && in_array($key, $field['value'])))))
                    <option value="{{ $key }}" selected>{{ $value }}</option>
                @else
                    <option value="{{ $key }}">{{ $value }}</option>
                @endif
            @endforeach
        @endif
    </ul>

    {{-- HINT --}}
    @if (isset($field['hint']))
        <p class="help-block">{!! $field['hint'] !!}</p>
    @endif
</div>

{{-- ########################################## --}}
{{-- Extra CSS and JS for this particular field --}}
{{-- If a field type is shown multiple times on a form, the CSS and JS will only be loaded once --}}
@if ($crud->checkIfFieldIsFirstOfItsType($field, $fields))

    {{-- FIELD CSS - will be loaded in the after_styles section --}}
    @push('crud_fields_styles')
        <!-- include text_suggestions css-->
        <link href="https://cdnjs.cloudflare.com/ajax/libs/awesomplete/1.1.2/awesomplete.css" rel="stylesheet" type="text/css" />
    @endpush

    {{-- FIELD JS - will be loaded in the after_scripts section --}}
    @push('crud_fields_scripts')
        <!-- include text_suggestions js-->
        <script src="https://cdnjs.cloudflare.com/ajax/libs/awesomplete/1.1.2/awesomplete.js"></script>
        <script>
            new Awesomplete('input[data-multiple]', {
                filter: function(text, input) {
                    return Awesomplete.FILTER_CONTAINS(text, input.match(/[^,]*$/)[0]);
                },

                item: function(text, input) {
                    return Awesomplete.ITEM(text, input.match(/[^,]*$/)[0]);
                },

                replace: function(text) {
                    var before = this.input.value.match(/^.+,\s*|/)[0];
                    this.input.value = before + text + ", ";
                }
            });
        </script>
    @endpush

@endif
{{-- End of Extra CSS and JS --}}
{{-- ########################################## --}}

How to use:

        $this->crud->addField([
            'name' => 'cities',
            'label' => 'Participating Cities',
            'type' => 'text_suggestions_from_array',
            'allows_multiple' => true,
            'options' => ['Chicago' => 'Chicago', 'New York' => 'New York', 'Boston' => 'Boston', 'Tokyo' => 'Tokyo'],
        ]);
chriscalip commented 6 years ago

Opened issue, as of today I am not able to complete this task; but someone might be able to finish this feature request.

tabacitu commented 6 years ago

Hi @chriscalip - looks like some great work you've done here.

It might be that I'm just dumb, but what is different between this field and select2_from_array, except for using a different JS plugin?

Thanks, cheers!

chriscalip commented 6 years ago

@tabacitu Think of it as the difference between a requirement and a suggestion. For the select element, the user is required to select one of the options you've given. For the datalist element, it is suggested that the user select one of the options you've given, but he can actually enter anything he wants in the input.

tabacitu commented 6 years ago

Oh, ok, I get it. In this case, we can totally add a flexdatalist or awesomplete field type.

I would personally prefer flexdatalist over awesomplete, since it looks like:

dandarie commented 2 years ago

Hi.

I was able to create a tags field with minimal effort using the dynamic option creation feature of select2:

$this->crud->addField([
            'name' => 'tags',
            'fake' => true,
            'store_in' => 'extras',
            'type' => 'select2_from_array',
            'allows_multiple' => true,
            'attributes' => [
                'data-tags' => true
            ],
            'options' =>[
                // existing options
            ],
        ]);

One caveat, though: the options array must have the same key and value for each item. Otherwise, the value sent to the controller is the numeric key of the item, for existing items.

'options' =>[
  'video' => 'video',
  'image' => 'image'
],

One obviously needs to provide a model mutator to save the new values and also some method to hydrate all options.

Now all you need to do is update the documentation :)

tabacitu commented 1 year ago

Whoaw - this suggestions sure has slipped through the cracks 😔 Trying to wrap up old issues, and like @dandarie said above, we can now do exactly this using the built-in select2 field. So I'm going to close this issue - I don't think an add-on for this is needed. I would happily publish a tutorial on this though, if anybody wants to write one in our Backpack blog. 1200+ developers would see it, and it's a great way to promote your own blog, brand etc.

Thanks a lot for collaborating here, Chris and everyone else. Apologies for replying so late. Cheers!

dandarie commented 1 year ago

More important is to update the docs. I myself have forgotten about this and needed it some time ago, then came back to this after searching for a solution.

Will this still work in v6?