indrimuska / angular-selector

A native AngularJS directive that transform a simple <select> box into a full html select with typeahead.
http://indrimuska.github.io/angular-selector
MIT License
96 stars 36 forks source link

Feature requests for `create` #35

Closed andreialecu closed 8 years ago

andreialecu commented 8 years ago

Leaving a couple of requests here :)

1) Currently the Add ... item is not shown when create is specified and other items appear in the list.

For example, in the bottom dropdown here: http://indrimuska.github.io/angular-selector/

I should be able to add "Ball" as a new item, but that is not possible.

Perhaps an attribute could be introduced, such as:

 <select selector
    ...
    can-create="canCreate(input)"
  ></select>

Where canCreate is a function that returns a boolean or a promise. This gives further flexibility to this solution so that certain items can be filtered out and not be allowed to be created (such as items that are too short, etc).

2) Would be nice if you could provide a promise as the create function.

In my case I want to display a modal when the Add .... item is selected, and only add it to the list/select it if the promise is fulfilled.

indrimuska commented 8 years ago

Hi @andreialecu, regarding point 1, create label in the dropdown should always be visible, so it needs to be fixed. Point 2. very nice feature request, I will work to make it real, but I don't know when, I don't have too much spare time these days.

indrimuska commented 8 years ago

FYI, v1.3.4 is now out with the fix for point 1.

andreialecu commented 8 years ago

Minor nitpick here, but the Add ... entry should be at the bottom, putting it at the top of the list is prone to user mistakes (at least in my app's case).

I worked around it by adding a fake entry at the end of the list as a placeholder which initiates the creation and setting create=false for now.

indrimuska commented 8 years ago

I don't think that Add.. label should be at the end of the dropdown, just because if the list has many entries you don't even know that this feature is available. Also, when you type something Angular Selector highlights first the first real item of the dropdown in order to help people choosing their value (simply by hitting Enter).

Anyway, you can change the basic template according to your needs:

angular
    .module('myApp', ['selector'])
    .run(['$templateCache', function ($templateCache) {
        $templateCache.put('selector/selector.html',
            '<div class="selector-container" ng-attr-dir="{{rtl ? \'rtl\' : \'ltr\'}}" ' +
                'ng-class="{open: isOpen, empty: !filteredOptions.length && (!create || !search), multiple: multiple, \'has-value\': hasValue(), rtl: rtl, ' +
                    'loading: loading, \'remove-button\': removeButton, disabled: disabled}">' +
                '<select name="{{name}}" ng-hide="true" ' +
                    'ng-model="selectedValues" multiple ng-options="option as option[labelAttr] for option in selectedValues" ng-hide="true"></select>' +
                '<label class="selector-input">' + /* ... */ '</label>' +
                '<ul class="selector-dropdown" ng-show="filteredOptions.length > 0 || (create && search)">' +
-                   '<li class="selector-option create" ng-class="{active: highlighted == -1}" ng-if="create && search" ' +
-                       'ng-include="dropdownCreateTemplate" ng-mouseover="highlight(-1)" ng-click="createOption(search)"></li>' +
                    '<li ng-repeat-start="(index, option) in filteredOptions track by index" class="selector-optgroup" ' +
                        'ng-include="dropdownGroupTemplate" ng-show="option[groupAttr] && index == 0 || filteredOptions[index-1][groupAttr] != option[groupAttr]"></li>' +
                    '<li ng-repeat-end ng-class="{active: highlighted == index, grouped: option[groupAttr]}" class="selector-option" ' +
                        'ng-include="dropdownItemTemplate" ng-mouseover="highlight(index)" ng-click="set()"></li>' +
+                   '<li class="selector-option create" ng-class="{active: highlighted == -1}" ng-if="create && search" ' +
+                       'ng-include="dropdownCreateTemplate" ng-mouseover="highlight(-1)" ng-click="createOption(search)"></li>' +
                '</ul>' +
            '</div>'
        );
    }]);
andreialecu commented 8 years ago

I know, but the keyboard selection will be off if I just modify the template.

The problem with the Add... label being first is that it is preselected so if you just hit enter it will create a new entry instead of the selecting the first entry below, which is what they would want 99% of the time. I would be ok with it staying first if simply hitting enter would select whatever was underneath it.

I'm using the control for searching from a person database, 99% of the time someone will be there, I'd like the users to not add duplicates - and this makes it easy to, especially with fatigue, since they use the picker a lot.

I'm migrating an app from chosen to this since it works better in some ways.

Edit: I notice that in the example on your site, hitting enter does actually select the one below. But in my app it doesn't - it picks the one that creates the item -, I'll try to make a repro.

andreialecu commented 8 years ago

@indrimuska Here's a repro: http://plnkr.co/edit/VTLCNJlB4Thwh0gRlNwM?p=preview

With remote the Add.. item is preselected, with options it works as expected.

indrimuska commented 8 years ago

Ok, I'm looking for the reason why your example has that behavior

indrimuska commented 8 years ago

Well, with any remote configuration the directive highlights the Add.. label reserved for option creation, no matter where the label is placed (at the top or at the bottom of the dropdown list). I found a fix and I'm just coding it.. :)

indrimuska commented 8 years ago

v1.3.6 is now out with this patch, waiting for your feedback! :)

indrimuska commented 8 years ago

Hi @andreialecu, in the last Angular Selector v1.3.7 I just added the ability to set a Promise for the create property. Check it out in the demo page (Create custom options (using Promise)) and let me know if it mets your needs.

indrimuska commented 8 years ago

Since all the requests have been marked as done, I'm going to close this issue. :)