Is it possible to post process data bound with angularjs?
I am writing simple search page and i have generated results with code:
...
<div class="row" ng-repeat="document in sc.searchResult.content">
<blockquote>
{{document.content}}
</blockquote>
</div>
...
The problem is that I need to bold specific words in every result (the words from query box - like in google below)
How to reach that effect?
controller.js
$scope.document.content = someSearchContent.replace(/<searchTerm>/g, '<strong>' + <searchTerm> + '</strong>')
searchTerm is the string that you need to modify. You can use RegExp() to create a regular expresion.
template
<blockquote ng-bind-html="document.content"></blockquote>
Related
I have a list
list = [
"Nrvana",
"Red Hot Chilli Peppers",
"R.E.M",
"Reef"
]
and on the html I am rendering the contents of this list.
<div *ngFor= "let x of list" > {{x}}
</div>
<hr/>
<div>
<textarea></textarea>
</div>
I also have a textArea , where a user can write anything he/she wants. Here is the tricky part and something I am unable to figure out. If a user uses syntax <<userText>> , a validation error should pop up stating Please use text from list inside <<>>. I can do this part but I can't figure out if I need to make a regex and if yes, please help me with it. Please ask if you need any more information.
p.s this is just something I created to get an idea of my problem, the actual project is a very long one and I am using template-driven forms
Here is a https://stackblitz.com/edit/angular-t4cfqc
Depends how you want to accomplish this and what you are exactly trying to do but you could do something like this
HTML
<textarea [(ngModel)]="textAreaText" [(ngModelChange)]="checkText()"></textarea>
.TS
textAreaText: string;
// ...
checkText() {
const regex = /(?:^|\s)<<(.*?)>>(?:\s|$)/g;
// If you only want to use certain keywords you could do something like this
const regex = /(?:^|\s)<<((keyword1)|(keyword2)|(keyword3))>>(?:\s|$)/g;
if (regex.test(this.textAreaText)) {
// do something
} else {
// do something else
}
}
You can make use of pattern attribute too. Example below
<textarea pattern="/(?:^|\s)<<(.*?)>>(?:\s|$)/g" [(ngModel)]="myTextArea" #myTextAreaModel="ngModel" required></textarea>
<div *ngIf="myTextAreaModel.errors.pattern">Your error msg here</div>
I am taking inputs from user, then adding links for mentioned users and then passing the same in the template
Input: hello #ds
String after adding links -
"#<a class="tweet-url username" href="/user/ds" data-screen-name="ds" rel="nofollow">ds</a>"
Passing the above string in .Msg (using golang template) :
<div class="panel-body" >
<p > {{.Msg}} </p>
</div>
Expected outcome is: Hello #ds (with clickable link on #ds)
However getting everything in text format (same as input).
#<a class="tweet-url username" href="/user/ds" data-screen-name="ds" rel="nofollow">ds</a>
What am I missing?
Got a better solution. First of all I am doing htmlEscape on the input then store it in db, then while presenting adding links followed by using document.write(string) function. With this I dont have to change the template and I dont have to worry about XSS attach. Also I am also avoiding XSS scripts in my database. –
Try wrapping your string (Msg) in template.HTML to disable the escaping that html/template does.
Example from the docs:
The template
Hello, {{.}}!
can be invoked with
tmpl.Execute(out, template.HTML(`<b>World</b>`))
to produce
Hello, <b>World</b>!
instead of the
Hello, <b>World<b>!
that would have been produced if {{.}}
was a regular string.
Note that you should do this with great care... make sure that you trust the string you're wrapping in template.HTML. This is an easy way to open yourself up to XSS attacks.
In angularjs, how to get the exact text as entered into html textarea, I want to also track newlines, '\n' (in the textarea). I want to store this textarea into database exactly the same as entered into textarea. But it is taking all text into one line.
How do I detect that new line is inserted into html-area?
Please see the demo
I can use <pre> {{someText}}</pre>, but this will not solve my problem, Because I want to store into database.
<div class="col-md-12">
<div class="col-md-6">
<label >Location Based Address </label>
<textarea rows="4" cols="25" class="form-control" ng-model="someText">
</textarea>
</div>
</div>
I belive that the model does save newlines and such, see this small edit on your plunkr, using a <pre> tag to display the data.
Also, when I save data to my SharePoint list, in a 'rich text' field, it saves newlines. I think your problem is that the server doesn't preserve the new lines.
Please check i have edited your plunker code. Check updated code
angular.module('app', ['ngSanitize'])
.controller('SomeController', function($scope,$sce) {
console.log($scope.someText);
$scope.$watch('someText', function(){
console.log($scope.someText);
$scope.text = $scope.someText;
$scope.text = $scope.text.replace(/\n\r?/g, '<br />');
$sce.trustAsHtml($scope.text)
})
})
Hope this will help you.
You could replace spaces with \n and store it that way, but I'm not sure how 'strong' this solution will be.
Value from the textarea is passed as is to someText via ng-model="someText". You don't need to do anything with the text as you can see in console.
If you want to print the value somewhere on your page while keeping new lines as the user entered them use <pre> tag:
<pre>{{ someText }}</pre>
Well i'm not really sure of what is happening but i'll try a wild guess of all things that can happens :
When using textarea, \n characters are stored in the value of the ng-model.
If you want to display them either use <pre> or replace all \n by and use ng-bind-html (https://docs.angularjs.org/#!/api/ng/directive/ngBindHtml)
If you want to send them to the server through json you may have to escape \n to \n same when sending data from the server to the client. Or it will be the underlying layers off your framework that will do it.
Make sure you're working with UTF-8 server-side/database or you may have problems with \r\n and \n.
I use CKEditor in my AngularJS Application. When I try to display the text that I saved from the TextEditor, it doesn't take the style. For Example if I want to display a sentence it appears as:
<p>How old are you</p>
instead of :
How old are you
I tried using ng-bind:
<div ng-bind="Item.Header"></div>
and the regular binding method:
<h3>{{Item.Header}}</h3>
But both methods didn't work. Is there a solution for this issue?
You should use "ngBindHtmlUnsafe". Since this command doesn't sanitize the expression, but you should only use it if you trust the source.
So the html will be written as follows:
<div ng-bind-html-unsafe="Item.Header"></div>
So let's say you display a list of divs that each represent a list item with certain properties (for an example a todo list):
<div class="list">
<div class="items" id="item1">
<div class="itemtitle">Some title</div>
<div class="icon"><img src="1.jpg"></div>
<div class="footer1" />
</div>
.
.
.
<div class="items" id="itemN">
<div class="itemtitle">Some other title</div>
<div class="icon"><img src="2.jpg"></div>
<div class="footer4" />
</div>
</div>
Now each item has three properties (title, a specific icon, and a custom footer). All these properties can be changed via javascript (say clicking on one cycles through the options).
Now everytime something is changed i want to save these changes to the server (and no, i don't want to store the whole html code block (that way i can't sort by the properties later, also it's ugly ;) ). What would be the most elegant and effective way to do this ? (I'm using jQuery if that helps...)
Thanks a bunch !
As long as you have a unique id for each block, you could push each change on blur of that element.
A user changes .itemTitle in #item4, you know the id is 4. So you can use an ajax post, send the item id, the item type (title), and the updated value. Then, on the server side (php, for example), you can do a simple mysql (i'm assuming) update.
Does that make sense? I can show actual code if need be.
If you want to transmit all the changes back to the server in one go, then naturally you need to put them into some kind of <input> element. <input type="hidden"> is the most obvious choice. If you go that route, you can either use an onsubmit handler on your form to update your hidden inputs from the text in the document, or you can update the hidden inputs in realtime as you update the document itself.
As far as how to structure the inputs, that's a harder question because there are several ways to do it and the best way to decide between them, it seems to me, is what's easiest to parse in your server-side framework.
You could create a whole bunch of hidden inputs with name="itemtitle" and a bunch with name="icon" etc, as long as your server-side framework knows how to interpret the resulting form post data as a list-of-values for itemtitle and for icon.
You could create hidden inputs with name="itemtitle1" etc.
Or you could just use one fixed hidden input and populate it with the entire list encoded in some form, such as JSON, if your server-side framework has an easy method for parsing JSON. Then you'd use javascript either in onsubmit or on every change to update the hidden input to consist of [{itemtitle="whatever", icon="whatever, ...}, {itemtitle="..."}] and parse that out as a JSON list on the server side.
Another choice would be to not use hidden inputs at all, but actual textboxes in the document itself. With styling, it's possible to make a textbox look un-editable. If you did that, then your list structure would post back all by itself when it's part of a form post.
One thing you can try is to collect the information into a JavaScript object literal, which essentially like a hashtable/dictionary structure, but you can nest structures inside. It's not a fixed structure, and doesn't require you to have hidden elements in your DOM -- you can have this completely separated from your DOM.
You can then take advantage of JSON notation for transferring this information to your server via a POST. Using Douglas Crockford's JSON2.js library allows you to serialize and de-serialize this structure to/from the object literal notation. And, there's lots of support for JSON on the server side.
So for your example, you could do something like this in jQuery (I extended your markup a little just to have a valid working example):
<div class="list">
<div class="items" id="item1">
<div class="itemtitle">Some title</div>
<div class="icon"><img src="1.jpg"></div>
<div class="footer1">blah</div>
</div>
<div class="items" id="item2">Stuff</div>
<div class="items" id="item3">Stuff2</div>
<div class="items" id="item4">
<div class="itemtitle">Some other title</div>
<div class="icon"><img src="2.jpg"></div>
<div class="footer4">boo</div>
</div>
</div>
(I'm assuming that your DIV ids are sequentially numbered -- item1, item2, item3, etc.)
and the JavaScript...
var theData = {};
$(document).ready(function() {
$(".items").click(function() {
theData["title"] = $(this).find(".itemtitle").text();
theData["icon"] = $(this).find(".icon img").attr("src");
theData["footer"] = $(this).find(".footer" + ($(this).index()+1)).text();
alert(JSON.stringify(theData));
});
});
(I'm assuming the footer data can be selected based on the sequentially numbered DIV id.)
Now that your changed data is in the theData object literal variable, you can send it to your server/service via a jQuery $.ajax call:
$.ajax({
url: "/ajax_json_echo/",
data: theData, //just pass the literal to your server...most can handle it
type: "POST",
dataType: "json",
success: function(data) { alert(JSON.stringify(data)); }, //output it readable form
error: function(x, t, m) { alert("Error: " + t + " :: " + m); }
});
You can check out a fiddle I put together that demos this.
I hope this helps!