What's the difference between ngBindTemplate and ngBind? - javascript

According to the docs:
The ngBind attribute tells Angular to replace the text content of the specified HTML element with the value of a given expression, and to update the text content when the value of that expression changes.
and
The ngBindTemplate directive specifies that the element text content should be replaced with the interpolation of the template in the ngBindTemplate attribute. Unlike ngBind, the ngBindTemplate can contain multiple {{ }} expressions. This directive is needed since some HTML elements (such as TITLE and OPTION) cannot contain SPAN elements.
My interpretation is that ngBindTemplate can do everything ngBind does, and more. So why do we even have ngBind?

As you can see in sources, ngBindTemplate involves $interpolate service, which:
Compiles a string with markup into an interpolation function. This
service is used by the HTML $compile service for data binding.

A simple metaphor for the difference:
ngBind only runs "objects".
ngBindTemplate only runs "strings"

Related

Angular why asterisk (*)

In Angular document, * and template, we know that the *ngIf, *ngSwitch, *ngFor can be expanded to ng-template tag. My question is:
I think the ngIf or ngFor without * can also be translated and expanded to template tag by Angular engine.
The following code
<hero-detail *ngIf="currentHero" [hero]="currentHero"></hero-detail>
would be the same as
<ng-template [ngIf]="currentHero">
<hero-detail [hero]="currentHero"></hero-detail>
</ng-template>
So why bother designing a strange symbol asterisk(*) in Angular?
Asterisk syntax is a syntatic sugar for more wordy template syntax which directive expands to under the hood, you are free to use any of these options.
Quote from the docs:
The asterisk is "syntactic sugar". It simplifies ngIf and ngFor for
both the writer and the reader. Under the hood, Angular replaces the
asterisk version with a more verbose form.
The next two ngIf examples are effectively the same and we may write in either style:
<!-- Examples (A) and (B) are the same -->
<!-- (A) *ngIf paragraph -->
<p *ngIf="condition">
Our heroes are true!
</p>
<!-- (B) [ngIf] with template -->
<template [ngIf]="condition">
<p>
Our heroes are true!
</p>
</template>
Angular2 offers a special kind of directives - Structural directives
Structural directives are base on the <template> tag.
The * before the attribute selector indicates that a structural directive should be applied instead of a normal attribute directive or property binding. Angular2 internally expands the syntax to an explicit <template> tag.
Since final there is also the <ng-container> element that can be used similarly to the <template> tag but supports the more common short-hand syntax. This is for example required when two structural directives should be applied to a single element, which is not supported.
<ng-container *ngIf="boolValue">
<div *ngFor="let x of y"></div>
</ng-container>
Angular treats template elements in a special way. The * syntax is a shortcut that lets you avoid writing the whole <template> element. Let me show you how it works.
using this
*ngFor="let t of todos; let i=index"
translates it into
template="ngFor: let t of todos; let i=index"
which is then converted into
<template ngFor [ngForOf]="todos" .... ></template>
also Agular's Structural directives like ngFor, ngIf etc. Prefixed by * just to differentiate them from other custom directives and components
see more here
From Angular docs:
Structural directives are responsible for HTML layout. They shape or reshape the DOM's structure, typically by adding, removing, or manipulating elements.
As with other directives, you apply a structural directive to a host
element. The directive then does whatever it's supposed to do with
that host element and its descendants.
Structural directives are easy to recognize. An asterisk (*) precedes the directive attribute name as in this example.
<p *ngIf="userInput">{{username}}</p>
Sometimes you may need <a *ngIf="cond"> for example, when it's only one tag. sometimes you may want to put the ngIf around multiple tags without having a real tag as a wrapper which leads you to <template [ngIf]="cond"> tag. how can angular know wether it should render the the ngIf directive owner in the final result html or not? so it's something more than just making the code more clear. it's a necessary difference.

Using class with angular vs ng-class while using a mixed expression

I have a div that I want to give a dynamic class with AngularJS.
The div is withing an ng-repeat statement where lang.prefix is first en then sv
Using the following code works and sets the class to i-flag-en than i-flag-sv, but is it correct?
<div class="float-left flag i-flag-{{lang.prefix}}"></div>
I know there exist a ng-class directive which can be used to dynamically set the class of an element with AngularJS.
I think I read somewhere in a book, that the normal class directive not should be used to set the class property dynamically with AngularJS because of the way Angular manipulates the dom.
However, the following code does not work:
<div class="float-left flag" ng-class="i-flag-{{lang.prefix}}"></div>
and I rather want to set the class in this way instead of creating another scope variable.
Is it bad practice to use the class attribute with AngularJS to dynamically set the class? Does it work all the time even if it would be bad practice?
The book you have mentioned may have talked about the problems of using ng-class and class {{}} interpolations together wherein updates in the interpolation removes the ng-class classes, this problem has already been resolved, reference. Thus, using interpolation within class attributes is totally fine, and does not break good practice because both has its own quirks.
Your usage of ng-class however is incorrect, you have to concatenate the literal string value with your scope string variable:
<div class="float-left flag" ng-class="'i-flag-' + lang.prefix"></div>
but I think it is much preferable to use your first example instead:
<div class="float-left flag i-flag-{{lang.prefix}}"></div>

Angularjs: variables in html attributes and within <style> markup

I would like to know how to put an angularjs model as the value for an html attribute. such as:
<div ng-controller="deviceWidth"
width={{width}}>
</div>
also, how would I do this within <style> markup? Where would I put ng-controller?
div {
width:{{width}}
}
Thanks,
Ben
You'd better do create own custom directive instead of the "static" width, and interpret the interpolation with $observe function.
Post pretty similar, involving some solutions:
String Interpolation Won't Work when Setting Attribute Values on a Custom Directive
Concerning the markup, you'd better play with ng-class, whose value comes from your controller logic.

Does jQuery internally convert HTML5 data attribute keys to lowercase?

I am trying to conform my JavaScript coding style to my Zend coding style as much as possible, which is using camelCase. So, in my HTML5 data attributes, I am naming them as in this example:
<button class="action" data-actionClass="user" data-actionMethod="delete" data-actionRequest="/user/delete/user-id/1" data-actionComplete="{reload:users}">Delete User #1</button>
<div id="users" data-reloadRequest="/user/index"> ... </div>
Pretty unobtrusive way to harness Jquery for actions, but when I call $('.action').data(), the attribute names are converted to lowercase.
Any workarounds for this?
I never though JavaScript variables should have dashes in them, and I can't understand why jQuery is internally doing this for me? Or maybe it is HTML5?
If you use
data-action-method="delete"
then you can access the attribute with
$('.action').data('actionMethod')
This is part of the HTML5 DOM API:
The custom data attributes is transformed to a key for the
DOMStringMap entry with the following rules:
any dash (U+002D) is removed;
any letter following a dash (U+002D), before its removal, is set in its uppercase counterpart.
First off, see this part of the source code of JQuery, it assumes you have lower case attributes.
Secondly, by convention, all HTML5 attributes should be lowercase, see: http://www.htmlbasictutor.ca/html-tag-attributes.htm
Finally, be warned you may encounter futher problems if you insist on using upper cases, see Django: Unable to add UPPERCASE attribute name in HTML input element

Accessing the value of an "em" tag in javascript

How would you access the value of an em tag in javascript?
This is the element I'm trying to access: <em id='tag_IS_System_Agent'></em>
which displays: John Smith
I'm trying to access it via javascript:
document.getElementById("emailFrame").src
= "http://www.website.org/mail.php?cid="
+IS_ATTR_ID.value
+"&name="+document.write("<em id=\"tag_IS_System_Agent\"> <\/em>")
+"&em="+email;`
Any idea? I know that document.write("<em id=\"tag_IS_System_Agent\"> <\/em>") is wrong and I'm stumped and not sure what to do.
Accessing the value based on your markup would be:
var myValue = document.getElementById("tag_IS_System_Agent").textContent
By “the value of an ‘em’ tag”, you apparently mean the content of an em element. If the element has an id attribute, as in your example, you can use the getElementById method of document to access the element node in the DOM. Then you can get the content of the element, serialized as HTML, using the innerHTML property. Note that this will include markup for inner elements, if any. So the expression you would use would be
document.getElementById('tag_IS_System_Agent').innerHTML
Instead of innerHTML, you could use textContent, which gives you just the textual content, without any inner tags. However, this is less widely supported (e.g., not in IE 8). If there is no inner markup, the results are the same, but innerHTML is thus safer.

Categories