Double curly braces in angularjs avoid w3c validation - angularjs

I have an html page that uses the following line of code:
... <a href="nolf://{{server.ip}}:{{server.hostport}}/"> ...
When I try to validate the page, I got the following error:
"Bad value nolf://{{server.ip}}:{{server.hostport}}/ for attribute href on element a: Illegal character in scheme data: not a URL code point."
It seems that the validator does not like seeing the curly braces in a URL link. If I remove them, all goes well. They are "unsafe" so they need to be encoded but if I encode them, the AngularJS instructions do not work anymore.
Is there a workaround, a way, to validate this? (original page where this code is can be found here: http://oneoakway.com/nolf/servers/ - there is a validation link in the footer)

Use ng-href instead. This will properly apply the expression to a href attribute.

Related

Why can't I use interpolation with a directive?

I have searched and found a few articles that address "How does one assign a scoped variable to the value of an html attribute tag". See:
https://docs.angularjs.org/guide/interpolation
How to assign angularjs variable value to html element attribute, such as input elememnt's name attribute
In my controller I have defined the following:
$scope.reportFields = "{'summary.imageID':'Image ID' }";
in my html document I have defined the following:
A TEST EXAMPLE
<button ng-json-eport-excel title="CSV" class="bt btn-md btn-success" separator="," data="mdcData" report-fields="{{reportFields}}" filename="'mySearch'">
when I bring the page into the browser I find that the page reports a parse syntax error on defining {{reportFields}} for my button element.
Error: [$parse:syntax] Syntax error: Token '{' invlaid key at column 2 of the expression [{{reportFields}}] starting at [reportFields}}].
if I forgo using a variable and hardcode the value as in:
<button ng-json-eport-excel title="CSV" class="bt btn-md btn-success" separator="," data="mdcData" report-fields="{'summary.imageID':'Image ID' }" filename="'mySearch'">
it compiles and works correctly. If I add the 'ng-if' it compiles correctly as seen below:
<button ng-json-eport-excel title="CSV" class="bt btn-md btn-success" separator="," data="mdcData" report-fields="{{reportFields}}" ng-if="reportFields.length > 0" filename="'mySearch'">
Furthermore when I examine the generated HTML via the inspector I can see that for the 'ahref' tag that angularjs's interpolation has translated 'reportFields' to '"{'summary.imageID':'Image ID' }"' for the ahref tag but it hasn't translate the value for the report-fields tag specified on the button. I have also tried:
ng-if="1==1" filename="'mySearch'">
for my expression which should always evaluate to true. My questions (and I am new to angularjs and I need help understanding) are:
Why do I get a syntax parse error for using the double curly angles with the second HTML element (button) but not the first (href)??
Why does the parse error go away with the 'ng-if' statement
Why doesn't the interpolation happen in the case for
report-fields="{{reportFields}}"
but occurs just fine for:
A TEST EXAMPLE
Thanks for your help in advance.
Pete
What you probably want is:
<a ng-href="reportFields">A TEST EXAMPLE</a>
Although this doesn't make any sense either given the way you've defined reportFields. Notice the ng-href and lack of interpolation. As it is, you are assigning the reportFields expression to the regular HTML attribute href which is not interpreted by Angular.
Angular treats your HTML like a template rather than trying to render it like a browser would. It takes that template and turns it into browser-readable DOM HTML. This helps explain the behavior you're asking about.
Answers to your questions:
Interpolation (curly braces) is actually a directive with special syntax which the parser has to evaluate along with any other directives such as ng-show, ng-repeat, custom directives, etc. There is no guarantee that an interpolation directive will be processed before another directive that tries to bind to it. And in fact, those other directives such as report-fields will get the raw interpolation markup and not the intended data. This is what throws the error. See the last paragraph in the interpolation documentation
Why mixing interpolation and expressions is bad practice
Since href is not actually a directive-- it's an attribute-- Angular doesn't attempt to treat it as a directive or bind it to the interpolation, so no error is thrown. It just outputs the expected result to the DOM: href="parsed value".
ng-if has no special assistance for this issue except it does get parsed before your report-fields directive and then cancels further parsing on the element if false. If you don't get an error in that situation, it's likely only because the if condition evaluated to false and the report-fields directive was never parsed. (Can't see all your code to confirm.)
The interpolation doesn't happen in the error case because the error is thrown before it has a chance to. Again, this is because it gets processed after other directive linking. (I'm not sure why they made that design choice though I imagine there is a good reason.)

AngularJS Protractor: select div with ng-show directive

I need to access to a div with a ng-show directive WITHOUT using xpath
<div ng-show="my_error && dirty_field">
Custom error message.
</div>
I tried these but it doesn't work properly
element(by.css('[ng-show=my_error && dirty_field]'));
and
element(by.model('my_error && dirty_field'));
How can I do?
Just to add few points here.
First of all, you definitely need the quotes around the ng-show value in this case:
element(by.css('[ng-show="my_error && dirty_field"]'));
This is because the value contains non-alphanumeric characters. See this related thread:
CSS attribute selectors: The rules on quotes (", ' or none?)
Also, I don't think you should use the dirty_field part in your locator. This sounds like a more technical variable used in the form validation logic. I'd use the "contains" check instead to check the my_error part only (note how I've removed the quotes in this case - the value is alphanumeric):
element(by.css('[ng-show*=my_error]'));
Also note that you can use the $ shortcut instead of element(by.css()):
$('[ng-show*=my_error]');
You cab deal with the properties this way in doing protractor testing.
element.all(by.css('[ui-sref="about_us"]')).first();
element(by.css('[ng-click="clickme()"]')),
element(by.css('[ng-show*=show_me]'));

How to use a angular controller with ion-tab to set badge count?

How to use a controller and assign badge number to a ion-tab using scope variable from the controller ?
I'm getting error when I tried this-
<ion-tab title="Home" badge={{homeBadgeCount}} ...
Syntax Error: Token '{' invalid key at column 2 of the expression angular
Please help...
Just figured out that I don't need to use the {{}} expression. Without that it works !!!
<ion-tab title="Home" badge=homeBadgeCount ...
As you can see, you can do it like badge=homeBadgeCount but that is not the best solution.
See w3schools / html attributes in section "We Suggest: Always Quote Attribute Values" to know why your solution works but is not the best practice.
Moreover, to know why your first try didn't work; I advice you to read these pages:
AngularJs directives, the official doc which explain how its parsing works
Stackoverflow - AngularJs - how are attributes evaluated
tl;dr write badge="homeBadgeCount" instead !

How to change valid HTML tags that get rendered in ng-bind-html?

I have a text editor (textAngular) that I've modified to limit the number of valid HTML tags I can generate using that tool. Now, I want to only support a limited number of HTML elements (h3, h4, h5, h6, ol, ul) to produce a news story but I want to disable some of the valid HTML rendered by ng-bind-html. Namely, I want to remove , tags as a valid tags because they could have disastrous results for this user generated content.
Is it possible to remove and tags as something rendered by ng-bind-html?
Unfortunately no, it isn't possible to config the valid HTML tags.
The ng-bind-html use the $sanitize service to strip invalid tags/attributes, and you can see in the source code that all the configurations are private.
// Safe Block Elements - HTML5
var blockElements = angular.extend({}, optionalEndTagBlockElements, makeMap("address,article," +
"aside,blockquote,caption,center,del,dir,div,dl,figure,figcaption,footer,h1,h2,h3,h4,h5," +
"h6,header,hgroup,hr,ins,map,menu,nav,ol,pre,script,section,table,ul"));
// Inline Elements - HTML5
var inlineElements = angular.extend({}, optionalEndTagInlineElements, makeMap("a,abbr,acronym,b," +
"bdi,bdo,big,br,cite,code,del,dfn,em,font,i,img,ins,kbd,label,map,mark,q,ruby,rp,rt,s," +
"samp,small,span,strike,strong,sub,sup,time,tt,u,var"));
If you really want it, one way you could do is to copy the angular-sanitize.js and modify the valid HTML tags configuration directly.
Please note that if you do it that way, all the ng-bind-html in your entire application will be also affected. If that is undesired, you have to write your own custom directive and inject/use your modified version of $sanitize instead.
If you're into modifying textAngular already, you could modify something around the taCustomRenderers Section of the code and use ta-bind instead of ng-bind-html. They do nearly the same thing except ta-bind runs all the extra renderers.
Custom Renderers Code: textAngularSetup, textAngular - probably in this one you can do your stripping out of unwanted code.

Is it possible to use multiple lines in Angular attributes?

Is is possible to include a newline in an Angular JS expression in an attribute tag? Something like this:
<p ng-repeat="
foo in foos
| filter:{attr: 'something really long'}
| orderBy:bar">
{{foo}}
</p>
EDIT: To clarify, the above doesn't work. I was wondering if there is some other syntax that allows for breaking this kind of expressions into multiple lines.
angular.js parser would be able to handle it, but there's a quick regex check before handing it to the parser (see http://docs.angularjs.org/error/ngRepeat:iexp):
Be aware, the ngRepeat directive parses the expression using a regex
before sending collection and optionally id to the AngularJS parser.
This error comes from the regex parsing.
I filed a bug to loosen this restriction: https://github.com/angular/angular.js/issues/5537, you can hand-patch it in the meantime, it's just 1 character: m (/regex/m).
It is possible for an expressions to span multiple lines. But ng-repeat throws an error if you try to span the expression on multiple lines.
Take a look at this plunker:
Add a new line in the ng-repeat expression and open the browser console to see the error message.
http://plnkr.co/edit/E1O8Iy3VzL3kzj72BDUL?p=preview
Yes, it is possible to use multiline attributes with ANY HTML element, including AngularJS directives.

Resources