Sign up ×
Stack Overflow is a community of 4.7 million programmers, just like you, helping each other. Join them, it only takes a minute:

I am building a search application.I am using the highlighter function from Johann Burkard's JavaScript text higlighting jQuery plugin. After an angularJS $Http call all the data is bound. I created a directive to call the Highlighter function.

searchApplication.directive('highlighter', function () {
    return {
        restrict: 'A',
        link: function (scope, element) {
            element.highlight(scope.searchText);
        }
    }
});

here is the controller `searchApplication.controller('searchController', function ($scope, $http, searchService) {

$scope.myObject= {
    searchResults: null,
    searchText: "",
};
$scope.search = function () {
    searchService.doSearch($scope.luceneSearch.searchText).then(
        function (data) {
            $scope.myObject.searchResults = data;
        },
        function (data, status, headers, configs) {
            $log(status);
        });
}

});`

here is the service

searchApplication.factory('searchService', function ($http, $q) {
return {
    doSearch: function (_searchText) {
        var deferred = $q.defer();
        var searchURL = '/Search';
        $http({
            method: 'POST',
            url: searchURL,
            params: { searchText: _searchText }
        })
        .success(function (data, status, headers, configs) {
            deferred.resolve(data);
        })
        .error(function (data, status, headers, configs) {
            deferred.reject(data, status, headers, configs);
        });
        return deferred.promise;
    }
}

});

In the html I have the following

<td ng-repeat="col in row.fields" highlighter>
     {{col.Value}}
</td>

The directive is not getting the value to be searched, rather it gets {{col.Value}} and hence it is not able to highlight.

What am I doing wrong? How can I get the actual bound values so that I can manipulate it? Is there a better way to do this?

Updated: with controller and service code

share|improve this question

1 Answer 1

up vote 2 down vote accepted

From the code given, it should work fine if your controller has $scope.searchText properly set. I defined your directive in my app and debugged the link() function in Chrome, and scope.searchText is found as expected. If from browser debugging you find scope.searchText to be undefined you probably need to also post your controller code here.


UPDATE: From your comment, it seems the problem here is the execution order within Angular. Apparently the linking function is getting called before text interpolation is finished, so the solution is to wait for that process before proceeding with the highlighting part.

The trick here is to $watch for an update in col.Value and invoke the highlight logic afterward. The code below should do the trick:

app.directive('highlighter', function ($log) {
    return {
        restrict: 'A',
        compile: function compile(element, attributes) {
            // at this point, we still get {{col.Value}}
            var preinterpolated = element.text().trim();

            // removing the enclosing {{ and }}, so that we have just the property
            var watched = preinterpolated.substring(2, preinterpolated.length - 2);
            $log.info('Model property being watched: ' + watched);

            return {
                post: function (scope, element) {
                    // we watch for the model property here
                    scope.$watch(watched, function(newVal, oldVal) {
                        // when we reach here, text is already interpolated
                        $log.info(element.text());
                        element.highlight(scope.searchText);
                    });
                }
            };
        }
    };
});

This time around, $log logic should print out the interpolated value instead of just col.Value.


UPDATE2: I'm not quite sure how to go from there with directive, but if you don't mind using Angular filter, you can try this Angular UI solution. After attaching js file to your page, just include 'ui.highlight' module in your app and the filter will be available for use. It's also small like your jquery lib as well:

https://github.com/angular-ui/ui-utils/blob/master/modules/highlight/highlight.js

You can try live example here:

http://angular-ui.github.io/ui-utils/

Your HTML should now look like this (directive is no longer needed):

<td ng-repeat="col in row.fields">
   {{col.Value | highlight:searchText}}
</td>

Also noted that now the CSS class for hightlighted text is ui-match instead of highlight.


UPDATE3: If you're set on using a directive, this person seems to do something very similar, except that he's adding a timeout:

http://dotnetspeak.com/2013/07/implementing-a-highlighting-directive-for-angular

setTimeout(function () {
    element.highlight(scope.searchText);
}, 300);
share|improve this answer
    
scope.searchText is showing me what the values are but in this line element.highlight(scope.searchText);. the element.node.data is not showing the bound value rather shows me {{col.value}}. I have updated my post with the service and controller. – gkbinary Jun 30 '14 at 15:27
    
@gkbinary Please see updated solution. I didn't use jquery nor hightlight plugin (my app is pure Angular), but at least from my testing the logic is now being executed after the text interpolation step. – b0nyb0y Jun 30 '14 at 17:12
    
this still leaves the text as is. I actually am seeing the values in scope.col.Value, So i tried doing this if(scope.col.value==scope.searchText) then scope.col.value = '<span class="highlight"'+ scope.col.value +'</span>'; this produces the result with the HTML as is rather than putting it in a span and applying the css. – gkbinary Jul 1 '14 at 2:29
    
@gkbinary Please see updated solution. It works if you don't mind using Angular filter instead of jquery function. This way you also don't need directive. – b0nyb0y Jul 1 '14 at 10:42
    
@gkbinary Also added another update in case you still want to try working a bit more on directive. – b0nyb0y Jul 1 '14 at 10:54

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.