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

AngularjsAngular UiAngular Ui-Typeahead

Angularjs Problem Overview


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")?

Angularjs Solutions


Solution 1 - Angularjs

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

Solution 2 - Angularjs

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"

Solution 3 - Angularjs

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.

Solution 4 - Angularjs

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

Solution 5 - Angularjs

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

Solution 6 - Angularjs

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

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionMatteo PiazzaView Question on Stackoverflow
Solution 1 - AngularjskrimhornView Answer on Stackoverflow
Solution 2 - AngularjsUmaKiranView Answer on Stackoverflow
Solution 3 - AngularjsdomenicrView Answer on Stackoverflow
Solution 4 - AngularjsSimon FakirView Answer on Stackoverflow
Solution 5 - AngularjsMatteo PiazzaView Answer on Stackoverflow
Solution 6 - AngularjsGio VeniceView Answer on Stackoverflow