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.
Related
I am learning angular js and have now a question where I couldn't find the right answer yet.
in the template HTML, you can use expressions to show the scope variables or call scope functions. But I see all the time different versions of it.
{{name}} shows the variable and binds it
{{::name}} the same thing but without binding
userdirective="{{::key}}" But what is the difference here?
ng-if="::field.sortable" With ng-if they are not using {{ but with there userdirective they do?
userdirective="{condition:isActive(route.name),mdColors:{color:'primary'}}" And then there is the last one with just one {. Thats when you create an object.right?
Maybe someone can help me to understand all of it.
Thank you very much for your time. Pat
{{name}} as you say is two-way data-binding
{{::name}} one way databinding
userdirective="{{::key}}" is the interesting case. This statement uses one-way binding into the userdirective ... which means after the $digest it just says userdirective="someValue"
So the userdirective gets that value as a plain value. Now I would have to test it but in the scopepart of the directiive it should say # so it gets read as a string and not as a expression.
The last one is simply as any JSON you build
{ name: value?true:false }
setting value according to conditions that angular evaluates, with a bit of magic involved :D
hope that helps
{{ anything here}} - That is angular expression interpolation. Angular interpolation - here you can find more about that. Basically idea that it interpolate anything you will put inside those brackets. So if you will put expression with some calculations or just variables related to current scope it will convert all variables to their values and apply calculations.
For instance: {{scopevar1 + scopevar2}} in case this variables has some values, let it be 1 and 2, as result we will see 3.
:: - This mean one time binding. For instance {{::scopevar1}} it will be interpolated once and will not check for changes of scopevar1, always stay as first value. Even if scopevar1 will change every second, the value in template will be the same. Angular Expressions - here you can find some live examples and more information.
userdirective="{{::key}}" - This case is nothing more then assigning dynamic value to your directive. UserDirective expectes to get a simple value, but we have it inside our scope, so we need to say: Hey, angular please interpolate scope variable - key, but only once, so my directive will get value, and will not looking for updates of key. And angular does it with pleasure!
userdirective="{condition:isActive(route.name),mdColors:{color:'primary'}}"
The last case is when your directive expects to get some kind of specific JSON. And we don't want to build it inside of controller. It is sometimes easier to do such things in the tempalte. So we put specific object with two properties: condition, mdColors. And saying that first property assigned to result of function, and second one is simple object {color:'primary'}.
That's it!
{{var}} is a two way binding expression and {{::var}} is a one-way binding expression. expression with :: will not change once set, it is a candidate for one-time binding.
go through : https://docs.angularjs.org/guide/expression for better examples on these
{{name}} is the regular case you will find. You basically print the variable name and update it once it changes.
{{::name}} is the same but your value will not receive updates once it stabilises.
So in the first case, your template updates once name is changed. In the latter, it isn't.
userdirective="{{::key}}" is a one-way one-time binding. Leave the :: out and your directive receives updates if key changes. However, if the directive changes key, it will not update the parent.
ng-if="::field.sortable" is a two-way binding. The changes go both ways. In this case, field.sortable is watched by the directive.
userdirective="{condition:isActive(route.name),mdColors:{color:'primary'}}" is used when you want to build adhoc-objects. A popular case is ng-class as well. You may build this object in the controller as well as you should not put too much logic in your template.
In any case, it is advisable to read the excellent docs https://docs.angularjs.org/guide
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.
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.
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.
I have this basic plnkr which just implements a basic "Hello, X" directive.
In the link function I am logging scope.name but I get undefined? Why is it so? Shouldn't it log the value of name property in console?
This is a known "problem" where interpolation of # attributes happens after linking function is invoked. There is a pull request open to change this issue but it is not clear if this one is going to be merged.
In the meantime a way of getting an interpolated value is by observing an attribute like so:
attrs.$observe('hello', function(changedValue){
console.log(scope.name);
});
And the plunk: http://plnkr.co/edit/Lnw6LuadTLhhcOTsPC8w?p=preview
So, at the end of the day this is a bit confusing behavior of AngularJS that might be changed in the future.
Pawel is right (https://stackoverflow.com/a/14552200/287070) but I wanted to add that the problem is that any attribute that contains {{}} interpolation will be set to null in the attrs parameter during the link function as the first $digest since the compilation has not yet run to evaluate these.
The fact that # bindings are null in linking functions is just a symptom of this.
Currently there is no real fix, since we can't start running $digests in the middle of the compilation process. So $observe (or $watch) is the only real way to get hold of these values.
For those in 2015 who are reading this post, please note that the way Angular handles "#" attributes has changed.
Angular 1.2 onwards, interpolation occurs prior to the invocation of the linking function.
An excellent post on this topic is present here.