I need to initialize an object in my view and assign a reference to it.
Can I achieve this by using ng-init? Is it an assignment by value or reference?
<ANY ng-init="objA = objB"> ... </ANY>
Any help will be appreciated!
Move assignment to controller init() method.
ng-init is directive that have a very lot of side effects and hardly to trace it down. For example: when you use ng-init in directive template for creating/editing item and you assign some model value in it - you will achieve problem with editing that actually should use already existing value.
As well side effect of it is executing few times when you add ng-if.
Usage ng-init in templates are your own risk.
Right way: controller data should be defined at start of module - in any case any view started in order: $state -> resolve() -> controller -> template -> directive. It's not a good idea to fool yourself with not existing data until it will be created by magic.
In case of repeaters when you have for example empty {} and you need to display it like possibility to fill yet empty input, as I mentioned - you need to run function on init that can define empty or extend existing model by passing actual model.
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
Here's a plnkr.
How do I access the headerInput model from within the sideMenuContent directive? Let's say I have 10 other ng-models in sideMenuHeader directive that I want to access in sideMenuContent, is there any way of making it easily scalable?
You need to use the dot notation for objects. See Understanding Scopes in AngularJs
So instead of headerInput, use something like menu.headerInput and also make sure to initialize a menu object in your controller like so $scope.menu = {}; (or you can also set default values).
I updated your plunkr to show you how it works
I have been following some of the introductory AngularJS tutorials and they start off by showing how easy it is to get started.
They say all you have to do is define ng-app and then use the example of an input with ng-model="name" and then show that string as you type using {{name}}.
My question is, is it possible to access and read the 'name' property without having to define a controller and read it using $scope.name?
For example..
$(function () {
var name = ?.name;
});
Well as it turns out, setting ng-model without a ng-controller defined at any parent level creates the item on the $rootScope.
What it also means that whereever $rootScope dependency can be injected you can get access to variable you define in the view.
See my fiddle here
Update: Based on the question update. You can access the scope outside from angular using something like
angular.element(domElement).scope()
and the access the variable. See this answer. But please avoid as much as possible.
First and foremost, the plunker: http://plnkr.co/edit/v1uTz5
This is a working demo of the issue I am running into.
I have a ng-include to include a partial.
Inside the partial I have an text input with ngModel AND directive.
The model updates accordingly inside the include, but any interaction outside the include is ignored. The {{test}} outside the include doesn't update, but the {{test}} inside does.
The directive, when called, handles the enter key and calls the correct scope and function. However, the $scope.test variable has never been updated, but $scope.testFinal is updated and the ng-include template renders it appropriately. Trying to reset the $scope.test model does not work either.
Am I missing something here? Or is this a bug with the directive or with the ng-include?
Instead of using a primitiive to define the variable, make it an object.
$scope.model={test:''};
Directives create their own scope for each item. When you equate a primitive to a new scope variable, it has no binding to the original, however when original is an object, a reference is created , not a copy, and changes made in one will reflect in the other
Simple explanatory example:
var a ='foo';
var b= a;
/* now change a*/
a='bar';
alert( b) // is still 'foo'
now do the same with object:
var obj_1= {a:'foo'};
var obj_2=obj_1;
/* now change obj_1.a*/
obj_1.a='bar';
alert( obj_2.a) // change to obj_1 will also change obj_2 and alert returns "bar"*/
Your Plunker Modified
Read this article on angular wiki for more detailed explanation
John Lindquist has a video about it. Although he doesn't quite explains why you need to use an object.
Basically every time there is a new non-isolated scope, every property of the parent scope is copied to the new scope and, as #charlietfl explained, copying a primitive type really creates a "copy" but with objects what you get is a reference, hence the changes are global.
ng-include creates its own scope and it is different than outer scope. Use this.test instead of $scope.test inside ng-include template. It will work properly.
I'm trying to change an input box value referring to its model.
The input box is inside an ng-repeat, that gets its elements from a function and not from a variable.
Is there a way for the application to print the model full path/name so that I can refer to it from the controller? (Note that the models are working, since a division beneath it with ng-show responds properly to the input model being filled.)
In general, you shouldn't use a function inside an ngRepeat. With the way the digest cycle works, your function will end up getting called multiple times. That's not very efficient. Instead, you should run the function from your controller and assign it to a scope variable that you pass to ngRepeat.
As it turns out, this makes the solution to your problem quite easy. You could for example use each item's $index to reference it from the controller.
If you post a fiddle or plunker, I can update this answer with something more specific. But it's hard to say more without some code.