I'm making a custom autosuggest component where I hit a web service with a search term and it returns a list of suggestions which I display.
My issue is, I want to bold the matching term inside the list and angular is not playing nice with the extra html. I've seen countless and countless examples using ng-bind-html which I've gotten to work if I can bind to specific values, but not with a dynamic list of values.
This is my first angular project so I'm sure there is something simple I'm missing. The code I'm posting renders the html correctly but it only displays the last result multiple times (I understand why).
How can I accomplish what I'm trying to do?
Here is my jade code :
#search-main(ng-controller="autocomplete" data-api-url="/autocomplete.json")
input(type="search" placeholder="Search" ng-model="termToComplete")
input(type="image" name="submit" src="/search-icon.gif", alt="Submit")
ul.autoSuggest(ng-if="items.length")
li.fade-in(ng-repeat="item in items")
h2: a(href="{{item.url}}" ng-bind-html="html")
Here is some of my js
app.filter('html', ['$sce', function ($sce) {
return function (text) {
return $sce.trustAsHtml(text);
};
}])
app.controller('autocomplete', function($scope, $element, $timeout, acAPIservice, $location, $sce){
$scope.items = [];
$scope.apiUrl = $element.attr('data-api-url');
$scope.termToComplete = undefined;
$scope.showSuggestion = function(){
var payload = {
term : $scope.termToComplete
}
acAPIservice.getSearch($scope.apiUrl, payload)
.success(function(data){
$scope.items = $scope.items.concat(data.results);
$scope.findMatch();
})
.error(function(data, status, headers, config){
$scope.items = [];
});
}
//iterates over the results and bolds matching terms
$scope.findMatch = function(){
var term = $scope.termToComplete;
angular.forEach($scope.items, function(value, key){
$scope.items[key].title = $sce.trustAsHtml($scope.items[key].title.replace(new RegExp('(^|)(' + term + ')(|$)','ig'), '$1<b>$2</b>$3'));
$scope.html = $scope.items[key].title;
});
}
$scope.$watch('termToComplete', function(newValue, oldValue) {
// reset everything
$scope.items = [];
$scope.start = 0;
$scope.end = 0;
$scope.total = 0;
// if we still have a search term go get it
if($scope.termToComplete){
$scope.showSuggestion();
}
});
});
Here is my test-Json :
{
"start" : 1,
"end" : 8,
"total" : 27,
"results" : [{
"id" : 0,
"title" : "here is a title",
"url" : "google.com"
}, {
"id" : 1,
"title" : "here is another title",
"url" : "google.com"
}, {
"id" : 2,
"title" : "and another title",
"url" : "google.com"
}]
}
NOTE:
acAPIservice
is just a factory that hits an API and returns the data
You don't need to define
$scope.html
because you are already assigning the HTML totitle
.You just need to use it right in your
ng-repeat
loop:I also recommend using
ng-href
instead of justhref
, because you are using an angular expression for the link ;)