I use AngularJS and have this code:
return text.replace("[", "<");
I expect it to add the < as a HTML character but it does not. It adds it as visible text. That way it print out the HTML code on the page.
How do I replace the less-than character <, without converting it to a text character?
Content of text
Before replace...
[div class="rating-container"]
HTML code
I added this, it's a value and a filter.
{{post.rating.html | replace_brackets }}
I tried to wrap it with
<div ng-bind-html-unsafe="post.rating.html | replace_brackets"></div>
but it just gave white nothing. No errors but no output.
Try this out
Working Demo
html
<div ng-app='MyApp' ng-controller="PostsCtrl">
<div ng-bind-html-unsafe="test | replace_brackets"></div>
</div>
script
var app = angular.module("MyApp", [])
.filter('replace_brackets', function($compile){
return function(text) {
var output = text.replace(/\[/g,'<').replace(/\]/g,'>');
return output;
};
});
app.controller("PostsCtrl", function($scope) {
$scope.test = "[div class='rating-container']Visible[/div]";
});
Related
I have a key-value pair that looks something like this ($ctrl.displayData)-
143:"/this/is/a/very/long/fil22↵/this/is/a/very/long/file/path.php↵anotherone.php↵newfilel123.php"
It saves file names and when I display it with an ng-repeat, file names are displayed in newlines (just as I want).
For display I use-
<div>
<div id="outputDiv" ng-click="$ctrl.deleteRow(displayData)" ng-repeat="displayData in $ctrl.displayData">{{displayData}}</div>
</div>
The function deleteRow() is pretty basic as of now-
ctrl.deleteRow = function(index){
console.log(index);
}
But when I loop through using ng-repeat, the entire {{displayData}} gets printed in just one iteration, so if I were to call a function like deleteRow() on click of any one file name, it just returns the entire set of file names each time (and not the particular file name that I have clicked on).
Is there a way of looping through $ctrl.displayData in such a way that on clicking any particular file name, the function is called only for that file name.
could you use javascript split?
// <body ng-app='myApp' binds to the app being created below.
var app = angular.module('myApp', []);
// Register MyController object to this app
app.controller('MyController', ['$scope', MyController]);
// We define a simple controller constructor.
function MyController($scope) {
$scope.files = "/this/is/a/very/long/fil22 \n /this/is/a/very/long/file/path.php \n anotherone.php \n newfilel123.php"
$scope.split = function(s) {
return s.split('\n');
}
$scope.doStuff = function(d) {
console.log(d);
}
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="myApp">
<div ng-controller='MyController'>
<p ng-repeat="d in split(files)">
<span ng-click="doStuff(d)">{{d}}</span>
</p>
</div>
</div>
I handled it inside the JS controller (using split there).
ctrl.arrayList = new Array();
for(var i in ctrl.displayData) {
ctrl.arrayList = ctrl.displayData[i].split('\n');
}
return ctrl.arrayList;
After this I use an ng-repeat on the array ctrl.arrayList for display inside the HTML file.
Here is what I want achieve: when user input some text, I will find the character a and using <em> tag to emphasize it in another <label>, here is my html markup:
<div ng-controller="demoController">
<input type="text" ng-model="input" />
<label>{{emphasize()}}</label>
</div>
As showing above, I'm using method emphasize in demoController to do emphasize job:
myapp.controller('demoController', function ($scope) {
$scope.input = 'Hello';
$scope.emphasize = function () {
return $scope.input.replace(/a/g, '<em>a</em>');
}
});
But the result is, the angular escape the <em> tag. For instance , if I input apple, then the label would show <em>a</em>pple, not I want: apple.
So why does this happened? Is there a way I can prevent this happen or another way to do it?
To do so a simple ng-bind-hmtl will do the trick :
<span ng-bind-html="emphasize()"></span>
But this is not really safe so it's always better to add this on your controller :
myapp.controller('demoController', function ($scope, $sce) {
$scope.input = 'angularJS';
$scope.emphasize = function () {
var res = $scope.input.replace(/a/g, '<em>a</em>');
return $sce.trustAsHtml(res);
}
});
add a filter to your module:
myapp.filter('unsafe', ['$sce', function ($sce) {
return function (a) { return $sce.trustAsHtml(a) };
}]);
and in your view:
<span ng-bind-html="emphasize() | unsafe"></span
I'm new to angular and experiencing some difficulty implementing a 'live search' type of feature. I have my JSON set as a variable in a javascript file and I am able to display that in the html with no problem. I then have a 'list' radio box which changes the size of the display. This is functional as well. I run into trouble, however, when accessing the reverse filter option which is denoted with another radio button. The intended result is to filter the book titles in reverse by their name, ye nothing happens. Here is my JSON if you want to see the structure. And below is the code where I try to perform the filter reverse action:
<div class="container result">
<div ng-class="list ? 'col-md-6' : 'col-md-4'" class="books" ng-repeat="books in books | filter:search | orderBy:'books.doc.name':reverse"> <a href="https://address/{{books.doc.name}}" target="_blank">
<img ng-class="list ? 'col-md-2' : 'col-md-12'" ng-src="{{books.doc.thumbnail_590_url}}" alt="Click to read {{books.doc.name}}" title="Click to read {{books.doc.name}}" class="img-thumbnail" /></a>
<h4 ng-class="list ? 'col-md-10' : 'col-md-12'">{{books.doc.name}}</h4>
</div>
and heres the js:
angular.module("myApp",["ngSanitize"])
.filter('replace', function () {
var pat = / /gi;
return function (text) {
var clean = text.replace(pat, "-");
var temp = clean.split("---");
if (temp.length>1) {
clean = temp[0];
}
return clean;
};
})
.controller("Example", function($scope, $interval) {
$scope.search = "orig";
$scope.books = books;
$scope.reverse = false;
$scope.list = false;
});
I figured this out. Angular filter will not work on a json object, rather the data must be in the form of a json array. I removed the highest level enclosing curly brackets and replaced them with square brackets in addition to removing the numbers and colons like "1272:" that can be seen in the json file I posted. Taking these steps converted my data to a json array and allowed me to use the live search functionality.
When I do a search in my application, I want to wrap the matching characters in the results with bold tags so you can see the matches.
So the results view looks like:
<ul class="search-results ng-hide" ng-show="(results | filter: filterQuery).length > 0">
<li ng-repeat="result in results | filter:filterQuery">
<h3><a ui-sref="{{result.state}}">{{result.name}}</a></h3>
<p>{{result.snippet}}</p>
</li>
</ul>
And the controller:
myApp.controller('SearchCtrl', function($rootScope, $scope, $state, Result, $location, $filter) {
$scope.query = ($state.includes('search') ? $location.search()['q'] : '');
$scope.filterQuery = ($state.includes('search') ? $location.search()['q'] : '');
$scope.results = [];
$scope.queryChanged = function () {
$scope.filterQuery = $scope.query;
if($scope.query){
$state.go('search', {'q': $scope.query} );
} else {
$location.search('q', null);
}
}
if($scope.query){
$scope.results = Result.query();
} else {
$location.search('q', null);
}
});
So I need to wrap tags around the result.name and result.snippet when it matches the filterQuery.
Something like (bits of this were copied from a PHP version I've done in the past, hence the mismatched syntax):
var keys = $scope.filterQuery.split(" ");
result.snippet.replace('/('.implode('|', keys) .')/iu', '<b>\0</b>');
But where would this go?
Create a search-result directive to wrap each search result, where name needs to be set as bold:
<search-result result="result" name="name" ></search-result>
With the following template:
directive.template: 'prefix text' + '<B>' + attrs.name + </B> + ' suffix text';
There's a few ways you could do this, mostly using filters.
You could write your own filter, that would take the string in the search, find it in the content that you are searching, and then add the tags around it and send it back.
Or, you can use one of the many plugins out there that does this.
Heres a question that talks about it
Angular UI Highlight
How can I mark my search pattern dynamically in my html?
Example:
I'm using angular and my html looks like this:
<div>
<input type="text" ng-model="viewmodel.searchString"/>
<!--Moving over all phrases-->
<div ng-repeat="phrase in viewmodel.Phrases">
{{phrase.title}}
</div>
</div>
I want the string matching pattern will be mark on every change in search string.
Can you help me?
Angular UI is a great choice. You can also do it with filter like: http://embed.plnkr.co/XbCsxmfrgmdtOAeBZPUp/preview
The essence is as commented by #Hylianpuffball, dynamically create styled 'span' tags for the matches.
.filter('highlight', function($sce) {
return function(text, phrase) {
if (phrase) text = text.replace(new RegExp('('+phrase+')', 'gi'),
'<span class="highlighted">$1</span>')
return $sce.trustAsHtml(text)
}
})
And use it like:
<li ng-repeat="item in data | filter:search.title"
ng-bind-html="item.title | highlight:search.title">
</li>
Just in case that someone (like me a moment ago) needs this for angular2:
highlight-pipe.ts:
import {Pipe, PipeTransform} from '#angular/core';
#Pipe({name: 'highlightPipe'})
export class HighlightPipe implements PipeTransform{
transform(text:string, filter:string) : any{
if(filter){
text = text.replace(new RegExp('('+filter+')', 'gi'), '<span class="highlighted">$1</span>');
}
return text;
}
}
and use it like this:
at top of file:
import {HighlightPipe} from './highlight-pipe';
in template where 'yourText' is the original text and 'filter' is the part you want to highlight:
<div [innerHTML]="yourText | highlightPipe: filter"/>
in component:
pipes: [HighlightPipe]
EDIT:
I updated it for RC 4
and created a plunker for testing:
http://plnkr.co/edit/SeNsuwFUUqZIHllP9nT0?p=preview
Try Angular UI
They have a highlight directive. You can use it as a reference to make your own (or just use it directly).
Inspired by #tungd's answer but valid for multiple search terms.
.filter('highlight', function($sce) {
return function(text, phrase) {
if (phrase){
phrases = phrase.split(" ");
for(i=0;i<phrases.length;i++)
text = text.replace(new RegExp('('+phrases[i]+')', 'gi'),'~~~~~$1%%%%%')
text = text.replace(new RegExp('('+'~~~~~'+')', 'gi'),'<span class="bold greenTxt">');
text = text.replace(new RegExp('('+'%%%%%'+')', 'gi'),'</span>')
}
return $sce.trustAsHtml(text)
}
});
PS: One can always limit the input to be in non-special chars for this to be 100% bullet-proof.