I'm trying to implement a typeahead in Angular using http://angular-ui.github.io/bootstrap/, where the typeahead field displays full addresses but once clicked another field is populated with just the postcode for that address. I'm trying to use ng-change or ng-click for this, but without any success..
http://jsfiddle.net/UxTBB/2/
angular.module('myApp', ['ui.bootstrap'])
.controller("mainCtrl", function ($scope) {
$scope.selected = '';
$scope.states = [{postcode:'B1',address:'Bull ring'},{postcode:'M1',address:'Manchester'}];
$scope.setPcode = function(site) {
$scope.selPcode = site.postcode;
};
});
<div class="container">
<div ng-controller="mainCtrl" class="row-fluid">
<form class="row-fluid">
<div class="container-fluid">
postcode <input type="text" ng-model="selPcode" />
typeahead <input type="text" ng-change="setPcode(site)" ng-model="selected" typeahead="state.address for state in states | filter:$viewValue" />
</div>
</form>
</div>
</div>
Any ideas?
The typeahead directive from http://angular-ui.github.io/bootstrap/ is very, very flexible and there are many ways of achieving the desired functionality. I'm presenting 2 of them here.
Firstly, the typeahead directive uses syntax very similar to the AngularJS select directive. This gives you full control over a displayed label and the data bound as model value. So what you could do is to simply display address as a label and bind postcode to the selPcode
directly:
<input type="text" ng-model="selPcode" typeahead="state.postcode as state.address for state in states | filter:$viewValue" typeahead-editable="false" />
The key here is the as
part is in the typeahead
expression: typeahead="state.postcode as state.address for state in states
Also, please note that I'm using the typeahead-editable="false"
attribute to bind model only when a selection is made. A working jsFiddle here: http://jsfiddle.net/jLupa/
Another solution, if you really need to use a callback function is to use the typeahead-on-select
attribute:
<input type="text" typeahead-on-select="setPcode($item)" ng-model="selected" typeahead="state.address for state in states | filter:$viewValue" />
It allows you to specify a callback when a match is selected. A working fiddle here: http://jsfiddle.net/t8BV2/
As the last note: ng-change
won't work here since it would react on any change in the input while you want to capture selection only. ng-click
is not of much use either as it reacts on clicking on the input field and not the matches popup. On top of this it wouldn't react on selections made by using keayboard.
@pkozlowski-opensource 's great solution has one drawback: you can't initialise the typeahead from the ng-model property in this way, at least if you want it to display the item's description and not its code.
I found a way to solve this by configuring the typeahead like this:
<input type="text" ng-model="selected" typeahead="state as state.address for state in states | filter:$viewValue" />
This returns a state object to the model property which can be initialised by setting the value to the appropriate object:
$scope.selected = {postcode:'M1',address:'Manchester'};
Working fiddle here: https://jsfiddle.net/0y3ntj4x/3/
I think this scenario is missing from the angular-bootstrap documentation for the typeahead.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With