Angularjs v1 : Is it possible to create a data-custom-directive atrribute? - angularjs

All is in the question :
I understood I have to declare the string with two custom letters than the uppercase word giving sense to the directive for example
djLoad
in the directive declaration which becomes
dj-load
in the view.
How about declaring
dataDjLoad
which would become
data-dj-load
in the view ?

The data prefix is stripped in the directive and attribute names by angular, so you should not use it. See "Normalization" section in the documentation.
The idea however is correct, directive declared as myDirectiveName (camelCase) should be used as my-directive-name or my:directive:name or my_directive_name in html.
If you still want to use the data prefix in your directive's name (e.g. dataDjLoad) - you should use it this way: <div data-data-dj-load></div>.
Here the EXAMPLE.

Related

my-Directive equals a string

I've started to work with dotansimha/angularjs-dropdown-multiselect directive. In the examples he shows the directive is being called out with an equals symbol followed by a undefined double quoted string as shown below.
<div ng-dropdown-multiselect="" options="example13data" selected-model="example13model" extra-settings="example13settings"></div>
My question what is the equals and undefined quotes used for in this example? Is this a way to isolate several of these controls on one page, pass parameters to the directive or does it not serve any purpose and is only a matter of coder style?
You can use this syntax to pass parameters to the directive, and it has some interesting uses. You can read more about it here.
In this particular directive's case, however, it doesn't seem to be doing anything,the documentation for angularjs-dropdown-multiselect does not address it. Given that the attribute parameters could still be accessed if ="" wasn't present, it can be considered style or unnecessary code, perhaps a leftover from a past implementation.

How is this custom tag configured?

I'm using this library https://github.com/tchatel/angular-treeRepeat
So to create a list of nodes this syntax is used :
<li frang-tree-repeat="node in treeData>
frang-tree-repeat is a custom tag and so it has to be configured somewhere within the library ?
Searching the src of https://github.com/tchatel/angular-treeRepeat I do not see any references to frang-tree-repeat so how is this tag configured or in other words how is frang-tree-repeat interpreted ?
Angular normalizes directive (both attribute and tag) names from kebab-case to camelCase. This is necessary since names of HTML tags and attributes are better written in kebab-case (because names are not case sensitive in HTML) while in Javascript kebab-case names would not be valid identifiers and could not be used for directives names (well, they could, but it would require additional wrapping into quotes).
That's the reason why you have to preform normalization from HTML notation to JS. Angular has $normalize service which is used for this. So it means, that if in HTML you have frang-tree-repeat it will be translated to frangTreeRepeat in Javascript.
In your case, your directive is found here: https://github.com/tchatel/angular-treeRepeat/blob/master/app/js/directives.js#L18
frang-tree-repeat is a custom directive which is defined in a module app.directives in angular-treeRepeat. As #dfsq pointed out, its implementation can be found here.
Note that it requires frangtreein its definition require: ^frangTree:
When a directive uses this option, $compile will throw an error unless the specified controller is found. The ^ prefix means that this directive searches for the controller on its parents (without the ^ prefix, the directive would look for the controller on just its own element).

Why do some angular commands use {{}}?

What is the difference between these two (why is one in {{}} and one in "")?
<body ng-controller="StoreController as store">
<img ng-src="{{store.product.images[0]}}" />
Oh, I think I see it now. The Store controller as store is a function, and the store.product.images[0] is a string, right?
So why is the ng-controller directive different? Well, it's just down to how the directives (the ng-xxx bit) are written. It's possibly a bit in-depth for this answer, but it would be worth looking at how to create custom directives (see https://docs.angularjs.org/guide/directive), and how you can pass data parameters to them.
The difference comes down to how the ng-controller and ng-src directives expect their parameters.
When something is between {{}}, you can think of it as identifying to Angular that this attribute value needs to be interpolated before it is passed to the directive. Interpolation is a form of compiling placeholders in a string, and it is a string that ng-src is expecting to be passed. So to give it the string value for a product image, it needs to use the {{}}.
So in your example, {{store.product.images[0]}} may be interpolated (think text replacement) to something like "\content\image1.jpg".
ng-controller will take care of parsing the value StoreController as store by itself, it's a syntax that only it knows about. As such, it just wants to read the attribute value as it is, with no preprocessing/interpolation.
I've simplified that a bit, but you can always check out more at https://docs.angularjs.org/api/ng/service/$interpolate for a bit more detail.
I hope that makes sense and I haven't confused the issue.

directive scope two way binding not working using "="

i have this very simple directive.
you can find the code here
In the code,
i have used '#' for link in the scope.
I am able to get it correctly.
But this is not two way binding, so i tried to do it with "=" in scope.
This part does not seems to reflect in my template. I tried to do see if the link variable
is present in scope,it seems to be undefined.
Should this directive be placed inside a controller?
What is that i am missing in my code.
You seem to be missing the difference between the # and = bindings. While the 2 might look similar those are fundamentally different ways of bridging "directive world" with the "page world".
Firstly, let's start with the similarities: both types of binding allows you to pass data from a page that is using a directive to the directive itself (directive intenal scope). But this is where similarities end, and the list of differences goes like this:
= is the 2-way data binding that can cross page / directive world in both ways: from a page to a directive and from the directive scope to the page scope. # on the other hand only allows you to pass data from a page to the directive and not from the directive to the page.
= binding allows you pass data defined on scopes - that is - any JavaScript variable (primitives, arrays, objects). # is different and is passing data through a DOM attribute. As such those attributes are restricted to Strings only.
given the above, the = and # are also triggered differently from the page that is using a directive: for = we need to pass an expression that points to data defined on the scope
while with # we are going through the DOM and need to use the interpolation directive ({{foo}}) to access data available on the scope.
After all those explanations you can see that using = in the directive definition we need to pass an expression so if you do this: <mydirective link="link1" group="main"></mydirective> you are effectively saying: pass to the directive a value of the link1 variable defined on a scope. Since such variable is not defined you are passing undefined to the directive.
So, if you intend to pass a constant (which I assume you want to do), you will need to write:
<mydirective link="'link1'" group="main"></mydirective>
Here is a working plunk: http://plnkr.co/edit/M3qL4MdmoWjTWzZGkwz0?p=preview
One thing most people forget is that you can't just declare an isolated scope with the object notation and expect parent scope properties to be bound. These bindings only work if attributes have been declared through which the binding 'magic' works. See for more information:
https://umur.io/angularjs-directives-using-isolated-scope-with-attributes/

AngularJS directive: attr with name of other directive

A simple example to explain my case:
I have a directive for labels
<input label="{{obj.label}}"/>
But for some other directives I want to use an attribute with name "label"
<other-directive label="My label"></other-directive>
just as an attribute, not processing the label-directive.
I could just rename the attribute to e.g. "my-label":
<other-directive my-label="My label"></other-directive>
but it would be nice to use "label" as an attribute name.
As #ExpertSystem points out in the comments to the question, angular really has no way of knowing out of the box whether your directive should be applied in one case versus another. The only way I can think of to get around this is to include logic in your directive's compile function that knows how to determine whether it should be applied or not. This plunker demonstrates how I would accomplish this. You basically need to return two different link functions from the compilation phase; one if your directive should be applied (in this case adding a label before the input), and a different one if it should be skipped. You are then free to use that as an argument to a separate directive. This may not work if your directive needs to do things like transclusion or isolated scopes (things that angular doesn't like two directives on the same element to do).
I'd be very sparing with how you use this, however, as it will create an inconsistent API for other developers who may be working with this code. They may not know when the directive will apply and when it won't.

Resources