web-dev-qa-db-fra.com

Autoriser la saisie manuelle du texte dans ui-select

J'utilise une boîte de sélection de ui-select. Tout fonctionne correctement, mais je veux autoriser le texte saisi manuellement et ne pas restreindre l'utilisateur à partir des valeurs disponibles dans la liste. Si je tape du texte, cela filtre ma liste correctement. Mais lorsque je ne clique pas sur un élément et que je passe au champ suivant, mon texte sera ignoré.

Des idées?

Merci et salutations, Alex Alex

Je ne voulais pas montrer mon code parce que je pense que ce n'est pas correct, mais cela a été demandé:

<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>

Les données sont stockées dans formData[field.id].selected. field.id est le numéro du champ actuel à afficher (je génère mon formulaire de manière dynamique). Supposons simplement qu'il stocke une valeur int unique.

Edit 08.04.2015 Ma solution: J'ai découvert qu'il semblait qu'il n'y ait pas d'équivalent à une liste déroulante en C #. Alors je suis allé de l'avant et utilisé deux champs distincts. Ce n'est pas ce que je voulais, mais ça marche pour l'instant:

<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>
30
AlexWerz

voici une solution: 

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>

MANETTE -

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

Voici la solution CodePen .

41
silverArc

Je pense avoir trouvé un moyen de permettre à l'utilisateur de créer de nouvelles entrées. Utilisez l'attribut "on-select" pour passer une fonction qui prend $ select en tant que paramètre, comme ci-dessous:

<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>

Créez ensuite la fonction qui ajoute une nouvelle entrée lorsque la variable clickTriggeredSelect est 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
};

Notez que la définition de personSearch n'est pas fournie ici. Cette approche consistant à tester clickTriggeredSelect peut également être utilisée pour permettre à l'utilisateur de désélectionner le champ si une entrée vide est la préférence.

PVC

13
Paul Van Camp

Vous pouvez utiliser l'attribut tagging comme expliqué dans la documentation: 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>
7
rave

J'ai créé le projet ui-select pour autoriser cette fonctionnalité via l'attribut 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>

Voici le plnker

Jusqu'à ce que ma demande d'extraction soit acceptée par l'équipe angular-ui, vous pouvez obtenir la version ui-select qui inclut mon correctif sur my own repo

4
aixki

J'utilise keyup pour ajouter une nouvelle option qui représente le texte saisi. Avec cette approche, si l'utilisateur appuie sur enter, il peut sélectionner ce qu'il a saisi jusqu'ici (l'élément actif par défaut est le premier élément).

Cela prend en charge les deux cas où la liste de données contient du texte brut ou un objet (l'attribut value-prop est requis).

Directif:

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>
0
Hp93