JQuery.html($sce.trustAsHtml("<br>loltest")) not working - angularjs

Here're video examples of what's happening:
Without sanitizing,
https://i.lithi.io/6GLS.mp4
With Sanitizing
https://i.lithi.io/TVIu.mp4
When clicked, this is supposed to make the text above, render the full text.
To do this, I have created a function
$scope.loadMore = function($event)
{
var element = $($event.currentTarget);
//console.log(element.data('text'));
var text = $scope.toHtml(element.data('text'));//$compile(element.data('text'));
//$sce.trustAsHtml(element.data('text'))
console.log(text);
if (element.parent().find('#text_data').length) {
element.parent().find('#text_data').html(text);
} else {
/*element.parent().find('#text_data').html(
element.data('text').length > 100 ?
element.data('text').substring(0, 100)
:
element.data('text')
);*/
}
}
I'm calling this function with ng-click. Basically it gets the parent, and then selects the element with the text inside.
The button has a Data Attribution with the full length text (not limited to 100 chars).
When I sanitize it inputs blank text? Whereas if I don't sanitize, it inputs the text.
I don't know if it's the right way to actually do it, but I just replaced the
tag with \n in my PHP, now it doesn't render them. Since YouTube doesn't support other HTML, it should be fine.

This is because your HTML is encoded. You have to decode it like this before displaying.
//angular hack to html decode
let decoded = angular.element('<div />').html(data).text()
$scope.decodedData = $sce.trustAsHtml(decoded);
There is nothing like $scope.toHtml(data)
Fiddle: https://jsfiddle.net/codeandcloud/54mzkjqe/

Related

angularjs calling select on corresponding HTMLinput doesn't highlight cell contents if value comes from ng-model?

I am trying to select (highlight) the text in an input element whose value comes from a model, but it doesn't seem to work.
The element (part of component template) in question is as follows:
<input id="table-input-cell" ng-blur="$ctrl.inputBlur()"
ng-focus="$ctrl.inputFocus($event)" ng-model="$ctrl.activeText"
class="input-cell"/>
The controller function looks like this:
ctrl.inputFocus = function(focusEvent) {
let el = ctrl.inputView[0];
console.log(el.constructor.name);
console.log(`inputFocus called. contents: ${el.value} `);
el.select();
};
What I am seeing as the result on the page is this:
What I would like to see is this:
Here's the console output:
HTMLInputElement
budget_controller.source.js:261 inputFocus called. contents:
So it looks like the problem is that the ng-focus may be called before the value of the input box is populated by ng-model, which is why .select() isn't highlight anything.
Or maybe it something else? Anyway, is there some other life-cycle event in AngularJs I can use to set the selection range once the element is bound as has focus? I don't see any thing ngBound= in the dox.
Use the event target:
ctrl.inputFocus = function(focusEvent) {
̶l̶e̶t̶ ̶e̶l̶ ̶=̶ ̶c̶t̶r̶l̶.̶i̶n̶p̶u̶t̶V̶i̶e̶w̶[̶0̶]̶;̶
let el = focusEvent.target;
console.log(el.constructor.name);
console.log(`inputFocus called. contents: ${el.value} `);
el.select();
};
The DEMO on PLNKR

ng-tags-input not working correctly with autocomplete

I'm adding tag by selecting from list (which is populated using $http request). The tag is added but the text which I have typed that remains there with ng-invalid-tag class.
ScreenShots
1) Initially,
2) Typing 3 letters to get HTTP Call.
3) Now after selection of first Skill "Angular Js'.
4) It shows that .input.invalid-tag is enabled. And which doesn't clear the placeholder.
My Input Tag is as below.
<tags-input ng-model="employerMyCandidatesCtrl.skillList" placeholder="Skills..."
replace-spaces-with-dashes="false"
add-from-autocomplete-only="true"
display-property="skillName"
on-tag-added="employerMyCandidatesCtrl.addTagToSkillData($tag)"
on-tag-removed="employerMyCandidatesCtrl.removeTagFromSkillData($tag)">
<auto-complete
source="employerMyCandidatesCtrl.loadSkillData($query)"
displayProperty="skillName" debounce-delay="500"
min-length="3">
</auto-complete>
</tags-input>
Controller Code is as below.
vm.skillList = [];
vm.loadSkillData = function(query) {
return EmployerServices.getAllSkillsPromise(query); // $http call.
};
vm.addTagToSkillData = function(tag) {
if (_.findIndex(vm.skillList, tag) < 0) {
vm.skillList.push(tag);
}
};
vm.removeTagFromSkillData = function(tag) {
var ind = _.findIndex(vm.skillList, tag) > -1 ? vm.skillList.splice(ind, 1) : '';
};
Is any configuration mistake I'm doing?
There are 4 attributes for onTagAdding, onTagAdded, onTagRemoving, onTagRemoved so the basic difference between the attributes ending with adding compared to those ending with added is
Adding suffixed tags are expecting a boolean which when true will be added
or removed based on the tag used.
But onTagAdded/Removed already adds the tag, before the function is called hence we can do some additional logic or else strip the ng-model of the added value or add back the removed value(not very easy).
Check the below JSFiddle to see the four attributes in action here
I have made a custom service to supply the data, so the final answer to your question will be to use the appropriate attribute (onTagAdding, onTagAdded, onTagRemoving, onTagRemoved) based on your usecase. From the above code, I think we need not write onTagAdded, onTagRemoved since its done automatically.

Make part of the text as link.(react - localization)

I need to mark part of the text as a link. Something like:
"Please log in with your email...". This text must be localized later.
I need that "log in" part to be the link.
When I do something like this in the render method:
var link = React.DOM.a({
href: this.makeHref('login')
},
'log in'
);// or React.createElement or
//var link = <a href={this.makeHref('login')}>
// 'log in'</a>;
<div>{'Please '+ link + ' with your email...'}</div>
It will output:
Please `[object Object]` with your email...
Without surround text, I receive the expected result. In other words: How to make react render HTML not object.
This is a simplified example - I need to insert link text with format marker {0} like in C# - or any other working solution.
Thank you for help!
If you want to use an element within another element, just use curly braces like so:
var Component = React.createClass({
render: function() {
var link = <a href={this.makeHref('login')}>log in</a>;
return <div>Please {link} with your email.</div>;
}
};
You can see a working fiddle here: https://jsfiddle.net/jrunning/fencjn4x/
If you're going to be internationalizing your app at some point in the future I recommend a) crossing that bridge when you come to it, and b) using a solution like React Intl instead of trying to build your own solution with string concatenation.

populate a form with a bookmarklet doesn't work in angularjs

I have a bookmarklet that just does some simple form input population but the angular form is still in an invalid state. Like nothing was ever changed.
I tried calling el.onchange() but that doesn't seem to do anything.
javascript:populate();
function populate(){
var name = document.querySelector('input[name=name]');
name.value = 'Fred';
name.click();
name.onchange();
}
Since I already have jQuery loaded, I was able to fix the issue by triggering the input event.
$('input[ng-model]').trigger('input');
I used something similar to the code below to create my bookmarklet.
Couple of things to consider.
Write your function (see example below)
Before creating your bookmarklet, test your function in the chrome console
Function tested, now remove the endlines (e.g. "replace all" in intellij (with regex enabled), replace "\n" with ""
create a new bookmark in the browser
edit the url, the url should begin with "javascript:", paste your one line url after that... you'll end up with something like "javascript:(function(){..." etc...
//nb: This function is not written to work in this page
(function () {
//get the scope object for your controller
var sc=angular.element("[ng-controller=myController]").scope();
//grab your model
var m=sc.mymodel;
//some 'dodgy' date strings :)
var today=new Date();
var todayAsString=today.toLocaleDateString("en-GB");
today.setDate(today.getDate()-183);
var sixMonthsAgoStr=today.toLocaleDateString("en-GB");
today.setDate(today.getDate()+365);
var sixMonthsLaterStr=today.toLocaleDateString("en-GB");
//pick a random oz state
var states=["WA", "VIC","SA", "NT","NSW", "ACT", "QLD"];
var ozState=states[Math.floor(Math.random()*(6)+1)];
//update the model with some semi random values
m.actionDate=todayAsString;
m.ausstralianState=ozState;
m.streetNum=Math.floor((Math.random() * 1000) + 1);
m.ID="CR" + Math.floor((Math.random() * 10000) + 1);
m.manufactureYear="" + Math.floor(Math.random()*(2016-1960+1)+1960); //approx... between 1960 and 2016...
m.endDate=sixMonthsLaterStr;
m.startDate=sixMonthsAgoStr;
//MUST call $scope.apply() at the end.
sc.$apply();
})();

How to stringify JSON to JavaScript array

My form in the html DOM is a checkbox to click (there can be more than one). The problem occurs in the description string when ever I use an apostrophe, since my list object is single-quote deliniated. This is one of the checkboxes in the form:
<input type="checkbox" id="cbx" name="cbx" value="{'getPic': 'url', 'picsrc': 'http://lh3.ggpht.com/_ZB3cttqooN0/SVmJPfusGWI/AAAAAAAADvA/GuIRgh6eMOI/Grand%20Canyon%201213_121508214.JPG', 'pos': None, 'description': 'Here's what it REALLY looks like at 5:30am! Bring your headlight!'}">
The javascript that reads the values of the checked checkboxes and pushes them into an array (list):
var pylist = [];
for (i=0; i<document.picList.cbx.length; i++) {
if (document.picList.cbx[i].checked) {
pylist.push( document.picList.cbx[i].value );
}
}
var getstr = JSON.stringify(pylist);
The problem is always that getstr at this point has chopped off everthing after the single quote in the description property.
I've tried different ways of escaping it to little avail.
The problem is that the value of the checkbox already is a JSON string. One solution would be to call JSON.parse() on the value:
var pylist = [];
for (i=0; i<document.picList.cbx.length; i++) {
if (document.picList.cbx[i].checked) {
pylist.push( JSON.parse( document.picList.cbx[i].value) );
}
}
var getstr = JSON.stringify(pylist);
I've run into the same issue - we stick json in a hidden field so we don't have to query the server on every page. We replace apostrophes with a "code" before putting into the html - we added a javascript function that replaces the code with an apostrophe.
Really hacky, but it works really well. Of course, we have one place in the code that gets json from the server and one place where javascript needs to parse it - if you find you're repeating the methods throughout your code, your mileage will vary.

Resources