so I have an Angular UI Typeahead that is working, however I have a use case that I can't get it to cooperate with.
My issue is getting it to display a certain value based not on user-input, which works, but based on the state.
I'm using Angular UI Router, so my code looks like this:
if($stateParams.assetID != undefined)
{
$http.get('/getData/idRepo', {
params: {
id: $stateParams.assetID
}
}).then(function(response){
$scope.getMaterial(response.data[0].Title);
//this is where I try and trigger the getMaterial
//function to show the Typeahead value based on a url parameter
//
});
}
$scope.getMaterial = function(val) {
return $http.get($scope.material[0].Query, {
params: {
title: val
}
}).then(function(response){
return response.data;
});
};
My Typeahead HTML is this:
<input type="text" ng-model="selected.asyncSelected"
placeholder="Material Name..."
uib-typeahead="med as med.name for med in getMaterial($viewValue)"
typeahead-editable="false"
typeahead-template-url="meditationssearch.html"
typeahead-select-on-exact="true"
typeahead-select-on-exact="true"
typeahead-loading="loadingLocations"
typeahead-no-results="noResults"
class="form-control">
As you can see, the typeahead reads from getMaterial()
which I try to trigger in my if($stateParams.assetID != undefined)
conditional.
Expected workflow:
$stateparam
for the assetID
in the url.assetID
param is not undefined, fire the GET request and then have it return the results from the running getMaterial()
(the result of the first GET request gets passed through getMaterial's() own GET request - as if the result of the first GET request were being typed in).getMaterial()
value in the view.I tried $scope.$apply()
but the digest is already in progress. I'm hoping there is another quick fix that I'm just not aware of to trigger the typeahead.
I also tried something like this:
jQuery("input[uib-typeahead]").val(response.data[0].Title).trigger('input');
...but that isn't a good solution because some of the assets I am type-aheading for have the exact same name, which is why I'm trying to use the id
as my url parameter and have the typeahead source function pick up the name as if it was typed in and then return to full object (name/id) to the model.
Please help me achieve my desired workflow.
Edit: Typeahead Source Code:
I believe I want to activate something in the select function:
scope.select = function(activeIdx, evt) {
//called from within the $digest() cycle
var locals = {};
var model, item;
selected = true;
locals[parserResult.itemName] = item = scope.matches[activeIdx].model;
model = parserResult.modelMapper(originalScope, locals);
$setModelValue(originalScope, model);
modelCtrl.$setValidity('editable', true);
modelCtrl.$setValidity('parse', true);
onSelectCallback(originalScope, {
$item: item,
$model: model,
$label: parserResult.viewMapper(originalScope, locals),
$event: evt
});
resetMatches();
//return focus to the input element if a match was selected via a mouse click event
// use timeout to avoid $rootScope:inprog error
if (scope.$eval(attrs.typeaheadFocusOnSelect) !== false) {
$timeout(function() { element[0].focus(); }, 0, false);
}
};
Maybe resetMatches()
? How do I call that from my own controller?
Another way to do it is to hook into the Typeahead itself, this way if it has the same name it will pick the right object for the model.
See here:
https://plnkr.co/edit/ABM72yyV4dtp5PsH4bIm?p=preview
angular.module('ui.bootstrap.demo').controller('TypeaheadCtrl', function($scope, $http,uibTypeaheadParser) {
$scope.fire = function(val){
var locals = {};
var model;
var parserResult = uibTypeaheadParser.parse(angular.element("input[uib-typeahead]")[0].getAttribute('uib-typeahead'));
locals[parserResult.itemName] = val;
model = parserResult.modelMapper($scope, locals);
console.log(model);
$scope.customSelected = model; //$scope.customSelected is the ng-model in this example
}
});
Where val
is an object, rather than a string.
<button ng-click="fire({
'name': 'Minnesota',
'flag': 'b/b9/Flag_of_Minnesota.svg/46px-Flag_of_Minnesota.svg.png'
})" class="button btn-primary">CLICK ME TO SET TYPEAHEAD</button>