Разрешить ввод текста вручную в ui-select

Я использую поле выбора из ui-select. Все работает нормально, но я хочу разрешить ввод текста вручную и не хочу ограничивать пользователя значениями, доступными в списке. Если я набираю текст, он правильно фильтрует мой список. Но когда я не нажимаю на элемент и не перехожу к следующему полю, мой текст будет отброшен.

Любые идеи?

Спасибо и с уважением, Алекс

Я не хотел показывать свой код, потому что считаю его неправильным, но он был запрошен:

<ui-select ng-model="formData[field.id].selected" theme="bootstrap">
    <ui-select-match placeholder="{{ lists[field.id].placeholder }}">{{$select.selected.text}}</ui-select-match>
    <ui-select-choices repeat="item in lists[field.id].list | filter: $select.search">
        <div ng-bind-html="item.text | highlight: $select.search"></div>
    </ui-select-choices>
</ui-select>

Данные хранятся в formData[field.id].selected. field.id - это номер текущего поля для отображения (я динамически генерирую свою форму). Просто предположим, что он хранит уникальное значение int.

Изменить 08.04.2015 Мое решение: я обнаружил, что похоже, что нет эквивалента выпадающему списку C#. Поэтому я пошел дальше и использовал два отдельных поля. Это не то, что я хотел, но пока работает:

<ui-select ng-model="formData[field.id].selected" theme="bootstrap">
    <ui-select-match placeholder="{{ lists[field.id].placeholder }}">{{$select.selected.text}}</ui-select-match>
    <ui-select-choices repeat="item in lists[field.id].list | filter: $select.search">
        <div ng-bind-html="item.text | highlight: $select.search"></div>
    </ui-select-choices>
</ui-select>
<?php echo __('Create a new element if value is not in list'); ?>
<div class="input-group">
    <span class="input-group-addon">
        <input type="checkbox" ng-model="disabled[field.id]">
    </span>
    <input type="text" value="" ng-disabled="!disabled[field.id]" class="form-control" ng-model="formData[field.id].newValue" />
</div>

person AlexWerz    schedule 07.04.2015    source источник
comment
Ну, я не уверен, почему меня минусуют. Было бы достаточно, если бы кто-нибудь мог указать мне на какую-то документацию. UI-select github предлагает несколько примеров, но ни один из них не содержит редактируемый текст.   -  person AlexWerz    schedule 07.04.2015
comment
Можете ли вы поделиться кодом?   -  person nalinc    schedule 07.04.2015
comment
Я не хотел делиться кодом, потому что я уверен, что он неверен. Я добавлю некоторые, если это поможет.   -  person AlexWerz    schedule 07.04.2015
comment
Мне нужна была эта функция в select2, и я почесал голову, чтобы заставить ее принимать свободный текст, но потом я понял, что typeahead создан именно для этого случая. Поэтому, если вам не нужен множественный выбор, это то, что вам нужно.   -  person roshan    schedule 10.11.2016


Ответы (5)


вот решение:

HTML -

<ui-select ng-model="superhero.selected">
  <ui-select-match placeholder="Select or search a superhero ...">{{$select.selected}}</ui-select-match>
  <ui-select-choices repeat="hero in getSuperheroes($select.search) | filter: $select.search">
    <div ng-bind="hero"></div>
  </ui-select-choices>
</ui-select>

КОНТРОЛЛЕР -

$scope.getSuperheroes = function(search) {
 var newSupes = $scope.superheroes.slice();
  if (search && newSupes.indexOf(search) === -1) {
    newSupes.unshift(search);
  }
  return newSupes;
}

Вот решение CodePen.

person silverArc    schedule 02.10.2015

Я думаю, что нашел способ разрешить пользователю создавать новые записи. Используйте атрибут on-select для передачи функции, которая принимает $select в качестве параметра, как показано ниже:

<ui-select ng-model="person.selected"
      theme="select2"
      on-select="peopleSel($select)"
      tagging
      reset-search-input="false"
      >

    <ui-select-match placeholder="Enter a name...">{{$select.selected.name}}</ui-select-match>
    <ui-select-choices repeat="sel in people | filter: {name: $select.search}">
    <div ng-bind-html="sel.name | highlight: $select.search"></div>
    </ui-select-choices>
  </ui-select>

Затем создайте функцию, которая добавляет новую запись, когда переменная clickTriggeredSelect имеет значение false:

$scope.peopleSel= function(sel) {
  if ( sel.search && ! sel.clickTriggeredSelect ) {
    if ( ! sel.selected || sel.selected.name != sel.search ) {
      //Search for an existing entry for the given name
      var newOne= personSearch( sel.search ); 
      if ( newOne === null ) {
        //Create a new entry since one does not exist
        newOne= { name: sel.search, email: 'none', country: 'unknown' };
        $scope.people.push( newOne );
      }
      //Make the found or created entry the selected one
      sel.selected= newOne;
    }
  }
  sel.search= ''; //optional clearing of search pattern
};

Обратите внимание, что определение personSearch здесь не приводится. Также этот подход к тестированию clickTriggeredSelect можно использовать, чтобы позволить пользователю отменить выбор поля, если пустая запись является предпочтительным.

ПВХ

person Paul Van Camp    schedule 18.06.2015
comment
ui-select v0.19 представил новую директиву uis-open-close. Если вы поместите функцию туда, а не в on-select, записи будут добавляться даже при размытии. - person ; 04.11.2016

Вы можете использовать атрибут tagged, как описано в документации: https://github.com/angular-ui/ui-select/wiki/ui-select

<ui-select multiple tagging tagging-label="(custom 'new' label)" ng-model="multipleDemo.colors">
...
</ui-select>
person rave    schedule 07.04.2015
comment
Большое спасибо, что указали мне на вики. Я искал документацию или примеры, но полностью пропустил вики. Тем не менее, теги - это не то, что мне нужно. Тегирование работает только при использовании multiple. Мне нужен выбор, который действует как выбор и ввод текста в одном элементе. Если ваш текст уже есть в списке, вы можете щелкнуть по нему, если нет, ваш текст будет сохранен. - person AlexWerz; 07.04.2015
comment
@AlexWerz: У тебя есть решение? Если да, то не могли бы вы поделиться им. Спасибо. - person Mithun Sasidharan; 19.06.2015
comment
Нет простите. Я использовал решение, которое я предоставил в редактировании выше. Но реального эквивалента C# Combobox не существует. Я переключил некоторые из своих графических интерфейсов на angular.js, у которого есть несколько дополнительных опций и возможностей. Может быть, вам тоже стоит взглянуть на него. - person AlexWerz; 19.06.2015
comment
Согласно официальному образцу angular-ui tagging не работает с одиночным выбором. Он работает только с несколькими ссылками на Официальный Образец пользовательского интерфейса Angular на Github - person M. Atif Riaz; 10.06.2019

Я разветвил проект ui-select, чтобы разрешить эту функциональность через атрибут allow-free-text.

<ui-select allow-free-text="true" ng-model="ctrl.freeTextDemo.color2" theme="bootstrap" style="width: 800px;" title="Choose a color">
    <ui-select-match placeholder="Select color...">{{$select.selected}}</ui-select-match>
    <ui-select-choices repeat="color in ctrl.availableColors | filter: $select.search">
      <div ng-bind-html="color | highlight: $select.search"></div>
    </ui-select-choices>
</ui-select>

Вот plnker

Пока мой запрос на включение не будет принят командой angular-ui, вы можете получить сборку ui-select, включающую мой патч, на мое собственное репо

person Anthony Hocquet    schedule 14.06.2016
comment
Мне нравится это решение. Каков статус/комментарии вашего запроса на включение? Не удалось найти его на GitHub. - person Lydon; 14.03.2017
comment
К сожалению, команда ui-select отклонила мой PR, вместо этого они хотят использовать свою систему тегов. Вот PR-ссылка: github.com/angular-ui/ui-select/pull /1659 - person Anthony Hocquet; 14.03.2017
comment
Было бы лучше, если бы вы сделали автономную директиву для этого. - person Immanuel Rosal; 15.09.2017

Я использую keyup, чтобы добавить новую опцию, представляющую введенный текст. При таком подходе, если пользователь нажимает enter, он может выбрать то, что уже ввел (по умолчанию активным элементом является первый элемент).

Это поддерживает оба случая, когда список данных содержит обычный текст или объект (требуется атрибут value-prop).

Директива:

commonApp.directive("uiSelectFreeText", function () {
    return {
        restrict: "A",
        require: "uiSelect",
        link: function (scope, element, attrs, $select) {
            var searchInput = element.querySelectorAll("input.ui-select-search");

            if (searchInput.length !== 1) {
                console.log("Error! Input not found.");
                return;
            }

            searchInput.on("keyup", function () {
                var valueProp = attrs["valueProp"];
                var addNewObjOption = function () {
                    // add new item represent free text option
                    var newOption = { isFreeText: true };
                    newOption[valueProp] = $select.search;
                    $select.items.unshift(newOption);
                };

                if ($select.items.length > 0) {
                    var firstItem = $select.items[0];

                    if (valueProp) {
                        // items is list of Object
                        if (firstItem.isFreeText) {
                            firstItem[valueProp] = $select.search;
                        } else {
                            addNewObjOption();
                        }
                    } else {
                        // items is list of string
                        if (firstItem === $select.search) {
                            return;
                        } else {
                            $select.items.push($select.search);
                        }
                    }
                } else {
                    if (valueProp) {
                        addNewObjOption();
                    } else {
                        // items is list of string
                        $select.items.push($select.search);
                    }
                }
            });
        }
    };
});

HTML:

<ui-select class="ui-select-control"
           ui-select-free-text value-prop="Label"
           ng-model="keyword">
</ui-select>
person Hp93    schedule 02.07.2018