Reputation: 35
Could you please help to highlight the words searched in yellow?
The below an example of code has been written to filter the words among the displayed data from JSON feed URL.
angular.module('sample', []).
controller('sampleController', ['$scope', '$http', function($scope, $http) {
var url = "https://spreadsheets.google.com/feeds/list/153Obe1TdWlIPyveZoNxEw53rdrghHsiWU9l-WgGwCrE/od6/public/values?alt=json";
$http.get(url)
.success(function(data, status, headers, config) {
$scope.users = data.feed.entry;
console.log($scope.users);
})
.error(function(error, status, headers, config) {
console.log(status);
console.log("Error occured");
});
// code to highlight
$scope.highlight = () => {
//create copy of the original array
$scope.filteredContent = JSON.parse(JSON.stringify($scope.users));
$scope.filteredContent.forEach(fc => {
const regEx = new RegExp($scope.search);
alert("here");
fc.question = fc.gsx$topic.$t.replace(regEx, '<span class="highlight">${$scope.search}</span>');
fc.answer = fc.gsx$response.$t.replace(regEx, '<span class="highlight">${$scope.search}</span>');
});
};
// code to highlight
$scope.search='';
$scope.searchFilter=function(item){
if(item.gsx$topic.$t.toLowerCase().indexOf($scope.search.toLowerCase()) != -1 || item.gsx$response.$t.toLowerCase().indexOf($scope.search.toLowerCase()) != -1){
return true;
}
return false;
}
}]);
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.2.0/angular.min.js"></script>
<div ng-app="sample" ng-controller="sampleController">
<div class="black">
<input type="text" name="search" ng-keyup="highlight()" ng-model="search" placeholder="search"/>
</div>
<br>
<br>
<br>
<table style="border: 1px solid black ;">
<tbody>
<tr>
<td>
<center><b>Question</b></center>
</td>
<td>
<center><b>Response</b></center>
</td>
</tr>
<tr ng-repeat="user in users | filter:searchFilter">
<td style="border: 1px solid black ; width:30%;white-space: pre-wrap;" ng-bind-html="user.gsx$topic.$t">{{user.gsx$topic.$t}}</td>
<td style="border: 1px solid black ; width:70%;white-space: pre-wrap;" ng-bind-html="user.gsx$response.$t">{{user.gsx$response.$t}}</td>
</tr>
</tbody>
</table>
</div>
Code link: https://jsfiddle.net/bjqsgfzc/1/
Upvotes: 3
Views: 666
Reputation: 5571
You'll need to use the $sce
service Strict Contextual Escaping.
Add this service in your controller declaration, like this:
controller('sampleController', ['$scope', '$http', '$sce', function($scope, $http, $sce) {
Now you must define a function that will only inject a span
tag with a CSS class name with the yellow color to highlight, when the searched text is found, through the $sce.trustAsHtml
method, to indicate AngularJS, the injected is safe content.
$scope.highlightText = function(text, search) {
if (search && search.length === 0) {
// Returns the default content.
return $sce.trustAsHtml(text);
}
// Define a regular expression to find the text globally and ignoring capital letters.
var regex = new RegExp(search, 'gi');
// If you already found the text then inject a span element with CSS class to highlight that you found.
return $sce.trustAsHtml(text.replace(regex, '<span class="foundText">$&</span>'));
};
In the previous regular expression replacement text, $&
indicates to display the captured text that matches the regular expression within the replaced.
In the HTML, within the ng-repeat
, add the ngBindHtml
directive with highlightText
function where the first parameter is the text that you'll have to search and the second parameter is the text to find.
In your case, in this way:
<tr ng-repeat="user in users | filter:searchFilter">
<td style="border: 1px solid black ; width:30%;white-space: pre-wrap;" ng-bind-html="highlightText(user.gsx$topic.$t, search)">{{user.gsx$topic.$t}}</td>
See in this example:
angular.module('sample', []).
controller('sampleController', ['$scope', '$http', '$sce', function($scope, $http, $sce) {
var url = "https://spreadsheets.google.com/feeds/list/153Obe1TdWlIPyveZoNxEw53rdrghHsiWU9l-WgGwCrE/od6/public/values?alt=json";
$http.get(url)
.success(function(data, status, headers, config) {
$scope.users = data.feed.entry;
console.log($scope.users);
})
.error(function(error, status, headers, config) {
console.log(status);
console.log("Error occured");
});
$scope.search = '';
$scope.searchFilter = function(item) {
if (item.gsx$topic.$t.indexOf($scope.search) != -1 || item.gsx$response.$t.indexOf($scope.search) != -1) {
return true;
}
return false;
};
$scope.highlightText = function(text, search) {
if (search && search.length === 0) {
// Returns the default content.
return $sce.trustAsHtml(text);
}
// Define a regular expression to find the text globally and ignoring capital letters.
var regex = new RegExp(search, 'gi');
// If you already found the text then inject a span element with CSS class to highlight that you found.
return $sce.trustAsHtml(text.replace(regex, '<span class="foundText">$&</span>'));
};
}]);
.foundText {
background-color: #ff0;
color: #f00;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.2.0/angular.min.js"></script>
<div ng-app="sample" ng-controller="sampleController">
<div class="black">
<input type="text" name="search" ng-model="search" placeholder="search" ng-click="didSelectLanguage()" />
</div>
<br>
<br>
<br>
<table style="border: 1px solid black ;">
<tbody>
<tr>
<td>
<center><b>Question</b></center>
</td>
<td>
<center><b>Response</b></center>
</td>
</tr>
<tr ng-repeat="user in users | filter:searchFilter">
<td style="border: 1px solid black ; width:30%;white-space: pre-wrap;" ng-bind-html="highlightText(user.gsx$topic.$t, search)">{{user.gsx$topic.$t}}</td>
<td style="border: 1px solid black ; width:70%;white-space: pre-wrap;" ng-bind-html="highlightText(user.gsx$response.$t, search)">{{user.gsx$response.$t}}</td>
</tr>
</tbody>
</table>
</div>
Hope this helps!
Upvotes: 1
Reputation: 1028
You can add <span>
with highlighted
class. Make sure to create a deep copy of the original array. I used JSON.parse(JSON.stringify(...))
. In addition, since we are adding the <span>
and want to display it as html
, we need to use ng-bind-html
. In order to do that, we need to add ngSanitize
as module dependency
.
angular.module('myApp', ['ngSanitize'])
.controller('myController', ['$scope', ($scope) => {
const content = [{
question: 'Question 1',
answer: 'Answer 1'
},
{
question: 'Question 2',
answer: 'Answer 2'
}
];
//create copy of the original array
$scope.filteredContent = JSON.parse(JSON.stringify(content));
$scope.highlight = () => {
//create copy of the original array
$scope.filteredContent = JSON.parse(JSON.stringify(content));
$scope.filteredContent.forEach(fc => {
const regEx = new RegExp($scope.searchText);
fc.question = fc.question.replace(regEx, `<span class="highlight">${$scope.searchText}</span>`);
fc.answer = fc.answer.replace(regEx, `<span class="highlight">${$scope.searchText}</span>`);
});
};
}]);
table {
border-collapse: collapse;
margin-top: 10px;
border: 1pt solid black;
width: 100%;
}
td {
border: 1pt solid black;
margin: 0;
padding: 0;
}
.highlight {
background-color: yellow;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.7.5/angular.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular-sanitize/1.7.9/angular-sanitize.js"></script>
<div ng-app="myApp" ng-controller="myController">
<input type="text" ng-model="searchText" ng-keyup="highlight()" placeholder="Search">
<table>
<tr ng-repeat="c in filteredContent">
<td ng-bind-html="c.question">
</td>
<td ng-bind-html="c.answer">
</td>
</tr>
</table>
</div>
Upvotes: 0