Angular-UI typeahead: show label but bind to value only
Asked Answered
V

6

54

I am using Angular-UI typeahead in the following way:

<input type="text" ng-model="myModel" typeahead="o.value as o.text for o in options | filter:$viewValue | limitTo:5" typeahead-editable="false" />

binded to a model like:

var options = [
    {"value": 1, "text": "value1"},
    {"value": 2, "text": "value2"},
    ...
];

It correctly shows options text, but when I select an item it shows inside the textbox the value. The model is correctly bounded to the value only (not the entire model object).

Is it possible to show inside the textbox the "text" (not the "value") after selection, still maintaining model binding to just the value (ie: when I select a certain "text" the model is updated with the "value")?

Visby answered 30/10, 2013 at 11:10 Comment(1)
Could you not use typeahead-on-select to set the selected value. Remove "o.value as" from type ahead.Ocker
S
53

It's not ideal, but the typeahead-input-formatter attribute provides a work-around until a fix can be provided. (Plunker from github thread).

HTML:

<input type="text" 
       ng-model="myModel" 
       typeahead="o.value as o.text for o in options | filter:$viewValue | limitTo:5" 
       typeahead-editable="false" 
       typeahead-input-formatter="formatLabel($model)" 
/>

AngularJs controller function:

$scope.formatLabel = function(model) {
   for (var i=0; i< $scope.options.length; i++) {
     if (model === $scope.options[i].value) {
       return $scope.options[i].text;
     }
   }
};
Slut answered 27/2, 2014 at 20:2 Comment(7)
Note: If you have a simpler formatting task, like accessing an attribute of the model, you can just do typeahead-input-formatter="$model.firstName + ' ' + $model.lastName".Hargis
And you can use Angular built in function to iterate through a collection or array: angular.forEach docs.angularjs.org/api/ng/function/angular.forEachAdermin
@NickM that won't work if you're using o.value as o.text syntax as the $model value reflects the parsed value of o.value, in this case a simple stringVomiturition
Hello, Did you able to make this work with Ajax source? Here is the GitHub bug reportAgateware
@NickM this keeps white space in input controlChurn
Unfortunately, this workaround doesn't work if you're populating the typeahead asynchronously.Roundelay
@NickMerrill @Vomiturition for this you should use only o and not o.value. @yehia use typeahead-input-formatter="$model && ... for keeping input clear when no valueMetempsychosis
O
28

Try changing your code from

typeahead="o.value as o.text for o in options | filter:$viewValue | limitTo:5"

to

typeahead="o as o.text for o in options | filter:$viewValue | limitTo:5"
Outofdoor answered 26/2, 2014 at 9:56 Comment(1)
but this sets the object to the model value instead of the id.Tantalizing
D
10

You can try doing as suggested but with typeahead-on-select like so

<input type="text" 
       ng-model="myModel" 
       typeahead="o as o.text for o in options | filter:$viewValue | limitTo:5" 
       typeahead-editable="false" 
       typeahead-on-select="model=$item.value"
/>

This will ensure that the text or label is displayed but underlying value is changed.

Dunsany answered 26/2, 2015 at 19:38 Comment(2)
this makes the assumption that you can be somewhat free to choose the format you ng-model will use. When restricted to simple types as in `ng-model="item.value", this will not work unless you proxy it somehow.Vomiturition
You should mention that model is not some what the as myModel. I use your method but model mean bind to the new model and used it in the controller. somehow the ng-model is still the object format.Xerosere
T
3

Here a shorthand formatter for everybody who uses lodash or underscore:

function formatTypehead(array,id){
  var o = _.find(array,{id:id});
  return (o?o.displayName || id:id);
}

and html:

<input  type="text" 
  uib-typeahead="s.id as s.displayName for s in companies | filter:$viewValue | limitTo:8"
  typeahead-input-formatter="formatTypehead(companies, $model)"
  ng-model="model.company"
  >
Tantalizing answered 12/8, 2016 at 14:53 Comment(0)
V
1

Well, so far I found a possible solution through directives.

HTML

<div my-autocomplete my-autocomplete-source="element" my-autocomplete-model="obj[element.model]"></div>

DIRECTIVE

app.directive('myAutocomplete', function() {
    return {    
        restrict: 'A',
        replace: true,
        template: '<input type="text" name="{{myAutocompleteSource.model}}" placeholder="{{myAutocompleteSource.label}}" ng-model="selected" typeahead="o as o.text for o in myAutocompleteSource.options | filter:$viewValue | limitTo:5" typeahead-editable="false" />',
        scope: {
            myAutocompleteSource: '=',
            myAutocompleteModel: '='
        },
        controller: function($scope) {
            $scope.selected = null;
            $scope.$watch('selected', function() { 
                $scope.myAutocompleteModel = ($scope.selected && 'value' in $scope.selected) ? $scope.selected.value : null; 
            });
        }
    };  
});

Well... obviously this is only a trick... I would like to know if is there a cleaner, more natural way to do it... without modifying code or using directive...

Visby answered 30/10, 2013 at 13:56 Comment(0)
L
0

for me this:

uib-typeahead="o as o.RagioneSociale for o in main.getLocation($viewValue)"

instead of:

typeahead="o as o.RagioneSociale for o in main.getLocation($viewValue)"

was really usefull

i had a json made like this:

[{"RagioneSociale":"Politi Real Estate sas","IDAnagrafica":"2516"},{"RagioneSociale":"COND METROPOLITAN","IDAnagrafica":"4325"}]


Model: {{asyncSelected | json}}
<input type="text" ng-model="asyncSelected" uib-typeahead="o as o.RagioneSociale for o in main.getLocation($viewValue)" typeahead-loading="loadingLocations" typeahead-no-results="noResults" class="form-control">

and it ended up in something like having the dropdown menu with just the RagioneSociale value and a model where i can see both the text and the id and print them with a normal {{asyncSelected}}

Linstock answered 24/10, 2016 at 23:1 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.