This question already has an answer here:
Do I still need to use data-ng with AngularJS or can I drop the data-?
(1 answer)
Closed 8 years ago.
I've come to know that data-ng-* is validation-friendly. But I've come across many places where I see snippets having ng-* over data-ng-*. Even the snippets in the angular official sites. Why is it so?
To embed custom non visible data we use data-. hence using data-ng- is suggested instead of ng-app To make it a valid html template.
Please refer : W3C
From the HTML 5.1 Editor's Draft,
3.2.5.9 Embedding custom non-visible data with the data-* attributes
A custom data attribute is an attribute in no namespace whose name
starts with the string "data-", has at least one character after the
hyphen, is
XML-compatible,
and contains no uppercase ASCII
letters.
And the official angularjs documentation:
What are Directives?
At a high level, directives are markers on a DOM element (such as an
attribute, element name, comment or CSS class) that tell AngularJS's
HTML compiler ($compile) to attach a specified behavior to that DOM element or even transform the DOM element and its children.
Angular comes with a set of these directives built-in, like ngBind,
ngModel, and ngClass. Much like you create controllers and
services, you can create your own directives for Angular to use. When
Angular bootstraps your
application, the HTML
compiler traverses the DOM
matching directives against the DOM elements.
And farther down the page:
Best Practice: Prefer using the dash-delimited format (e.g. ng-bind for ngBind). If you want to use an HTML validating tool,
you can instead use the data-prefixed version (e.g. data-ng-bind
for ngBind). The other forms shown above are accepted for legacy
reasons but we advise you to avoid them.
So directives of the form data-ng-* are only necessary if you want your HTML to validate. Otherwise, it's "deprecated". Use ng-* instead.
Related
I totally hate to add tag names based on component names in my apps. I hate to do this:
<hero-detail hero="ctrl.hero"></hero-detail>
Isn’t it possible to use normal div tags instead? Something like this?
<div id="hero-detail" data-hero="ctrl.hero"></div>
why isn’t that working?
You can technically restrict a component to an attribute as you do with directives since components are a special kind of directive. (I modified a random fiddle found on google)
EDIT: this does work on older 1.5 versions but not on newer ones. So read on...
But officially you cannot and you shouldn't do it anyway. If you choose a component architecture, you have to stick to the rules or things will get out of hands quickly.
Having components as html elements is clean and good practice. You should learn to like it.
why not, that is also possible.
basically in three ways we can specify the directives.
i.e Element, Attribute, Classname
but while create the directive you can specify
restriction : AE
or whaterver you need,
then you can use like this
<div id="hero-detail" hero-detail data-hero="ctrl.hero"></div>
for more have a deep look at the docs. directives
your answer is here https://docs.angularjs.org/guide/directive
They says:
Directive types $compile can match directives based on element names,
attributes, class names, as well as comments.
All of the Angular-provided directives match attribute name, tag name,
comments, or class name. The following demonstrates the various ways a
directive (myDir in this case) can be referenced from within a
template:
<my-dir></my-dir>
<span my-dir="exp"></span>
<!-- directive: my-dir exp -->
<span class="my-dir: exp;"></span>
Best Practice: Prefer using directives via tag name and attributes
over comment and class names. Doing so generally makes it easier to
determine what directives a given element matches.
Best Practice: Comment directives were commonly used in places where
the DOM API limits the ability to create directives that spanned
multiple elements (e.g. inside elements). AngularJS 1.2
introduces ng-repeat-start and ng-repeat-end as a better solution to
this problem. Developers are encouraged to use this over custom
comment directives when possible.
Sometimes when I build an Angular custom directive, I will hear a comment as to, if it is an Angular directive, it should not use jQuery code in it, because it should be built in an AngularJS way.
And I thought it might be true, but is it possible? For example, what if the directive template has 2 sections, one is the words and one is the tiny images (such as review stars), and so you need 2 sections in your template, labeled as .description and .star-images -- so then you should need to use $.find(".description") to find that section inside your template if you need to do something to it or inside it. jqLite won't work as jqLite's find() is limited to tags only.
Another example is, what if you have a directive that doesn't have a template, but just limit the keypress to digits only, say, for an input box. So you don't want your directive to have a template as <input type="text"> but just want the user of the directive to say <input type="text" digits-input-only> and your directive is called digitsInputOnly. So in that case, don't you need to use jQuery's elem.on() or elem.bind() to listen on keypress or keydown events, and when the key down code is not a digit, then do a event.preventDefault()? So in that case, it has to use jQuery?
Or other there other ways to do it so that you really shouldn't need to use jQuery?
As a long time user of jQuery it is easy while learning angular to lean on jQuery however none of the cases mentioned are difficult to work around not having it...and in most cases are actually easier
Try removing jQuery completely from your project to avoid temptation and you will quickly realize how little you really need it
The core directives provide the majority of the event handlers needed and angular.element (jQlite) also has bind() which will accept virtually any event name. $document.bind('contextmenu', function(event) for example.
The core dom event directives all let you pass in $event for things like event.preventDefault()
<input ng-keydown="somefunc($event)">
For traverses you can always use a native method to query DOM to find an element and wrap that element (or collection) in angular.element() the same way you would with $(). The more you focus on data models and core directives first however, the less you find need to actually do dom traverses
As for plugins ... it's not a sin to use jQuery plugins in directives. There are some very commonly used angular modules that are wrappers for well known jQuery plugins ... fullcalendar and Datatables are a couple that quickly come to mind along with numerous datepickers. However often you will find situations where you may have previously leaned on a plugin to do simple tasks that angular makes easy itself and you no longer would use such plugins
The sin with using jQuery plugins is using ones that are actually easier to achieve (and test) using angular itself
In conclusion, the biggest adjustment is learning how to focus on data models first, before thinking about the DOM. Also being intimately familiar with the left side menu of the API reference where all the core directives and services are listed is a huge help
Everyone (W3C validator, stackoverflow posts, etc) says you should prefix custom attributes with data- (e.g. data-my-custom-attr="hey"). And you shouldn't use them like: my-custom-attr="hey".
Yet Angular encourages you to use things like ng-click etc without the data- prefix.
Is this just a question of best practise? Or is Angular being a bit of a maverick?..
Why do you say that angular encourages it? In fact if you check normalizations section for directives in angular documentation you will find a note that angular in parsing directives strips data- and x- prefixes so you don't have to access attributes and name directives like
.directive('dataMyCustomDirective', function(){})
but nothing tells you you can't or shouldn't use data- or x- prefix if you want your HTML to be validated against w3c validator, i personally use attributes without the prefix in development and use grunt task to add prefix for production
That's an interesting question. But I think it's more of a personal use. I use a custom prefix for all the attrs and declarations I create with the company prefix. e.g. mj-function -> MyJob-Function. Nothing stops me from doing this ang ignoreing the data- prefix.
This also helps me keeping the code more organized (if using third part libs). Because it's easy to locate. MJ is code built by myself. ng is Angular. Other is third.
Keep an eye!
What you have to avoid is to declare your attrs with the prefix ng if you are using AngularJS, because then you could have a conflict with AngularJS main directives. Like ngClick, ngChange, ngBlur, etc...
But nothing about use/not use data- prefix.
I have jsonData which consist of HTML content. I want to render that HTML in ng-grid. The content is not rendered however -- it only shows up in normal string format.
Below is the plnkr which shows all the code:
http://plnkr.co/edit/RlWyDqCUUR15dmLM7ePV?p=preview
There's a few things going on here:
Not related to your exact issue, but you've got nested single quotes in your firstName field. You need to do some escaping or your ng-click expression is going to break. So instead of ng-click='show('F:/cox/main.html')' you can do ng-click=\"show('F:/cox/main.html')\".
Also not related to your exact issue, but if you want to access properties on your controller's scope from inside UI-Grid you need to use appScope. The docs on it are here: http://ui-grid.info/docs/#/tutorial/305_appScope
The main problem with getting HTML provided from inside your app to render is Strict Contextual Escaping.
Strict Contextual Escaping (SCE) is enabled by default in Angular and escapes any arbitrary HTML to prevent things like XSS and clickjacking. In order to get your HTML to show up you need to trust it, and bind it with an HTML bind expression.
You can use the $sce service to trust the HTML. Just iterate over your rows and do $sce.trustAsHtml(row.firstName). (You can read more about SCE here: https://docs.angularjs.org/api/ng/service/$sce) Then you will need a custom cell template to bind the HTML. The simplest one looks like this:
<div class="ui-grid-cell-contents" ng-bind-html="COL_FIELD"></div>
COL_FIELD will get transformed by UI-Grid into the proper binding for your field. Now the problem is that your ng-click directive doesn't get compiled. You need to use a directive that will take your custom HTML and compile it. You could roll your own, or use something like this library to do it for you: https://github.com/incuna/angular-bind-html-compile
The main thing to keep in mind is being able to actually trust the source of your HTML. If you can't be sure then going about this another way (i.e. by not providing HTML inside your data set) would be better.
I've modified your plunker to show all this working together: http://plnkr.co/edit/MgLoeGBoRTi2fF3e6pia?p=preview
Assuming that a Custom Directive:
define a custom tag or attribute that is expanded or replaced
can include Controller logic, if needed
and that the Directive can be of type Element
<my-customdirective></my-customdirective>
or of type Attribute
<h4 my-customdirective></h4>
my question is WHEN and WHY I decide to use one rather than another?
Quoted from the documentation:
When should I use an attribute versus an element? Use an element when
you are creating a component that is in control of the template. The
common case for this is when you are creating a Domain-Specific
Language for parts of your template. Use an attribute when you are
decorating an existing element with new functionality.
Some points to consider:
Most of the time attributes is the best/most convenient option (it's not the default by chance).
Anything you can do with element-bound directives, you can do with attribute-bound as well.
Element-bound directives can be more descriptive/readable at times.
If you want your code to pass certain types of validation, you should use attributes.
Since you want to support IE8, keep in mind that custom tags have an extra overhead (more info), which hurts maintainability.
For More Details