How do you implement one-way binding? Please provide some explanation on why and when you would use one-way binding.
I'm new to AngularJS.
Please provide some explanation on why and when you would use one-way binding.
Possible Reasons:
You want to speed up your app.
You want your Angular 1 to have an easier upgrade path to Angular 2
You have a value that you want to pass to several children, but when the children change the value, you don't want the other children to sync this change.
How do you implement one-way binding?
Before Angular 1.5 you can make a make a deep copy of your object with angular.copy once you pass it in, so e.g. myVal = angular.copy(myVal). After Angular 1.5, you can use < in your bindings, which would then look like that:
bindings: {
myVal: "<"
}
However, note that if myVal is an object, you'll still have to do the deep copy using angular.copy, the "<" only works for non-object values. See the following plunkr to see what I mean.
Related
Trying to have 2 way binding on an AngularJS directive while using primitive objects is not working, for example:
<custom-directive ng-model="variable"></custom-directive>
how can this be achieved?
In order to have 2 way binding in javascript (not just angularjs), we have to pass an object (this is caused by javascript's evaluation strategy - can read more about it here https://en.wikipedia.org/wiki/Evaluation_strategy#Call_by_sharing). basically what is happening is that when we pass a primitive variable, its been passed by value and re-created, instead of been passed by reference. only objects are passed by reference.
So this issue can be solved by passing the variable's parent object, for example:
<custom-directive ng-model-name="variable" ng-model-parent="parentObj"></custom-directive>
and then, modifying in object in the directive as following:
parentObj[variable] = "whatever";
this way, we will keep the connection between the variable to the parentObj.
another option would be passing the model with the parent obj, for example:
<custom-directive ng-model="parentObj.variable"></custom-directive>
the dot is an important part of this example. its actually a best practice by angular to always pass variables with the parentObj-dot-property.
for additional information, angularjs actually has a documentation about it https://github.com/angular/angular.js/wiki/Understanding-Scopes
I just realized that if your directive isn't inside an ng-if it will work with primitive bindings. Maybe the problem is that your bind is inside an ng-if. Try to use ng-show instead. Maybe it will work.
Passing the primitive this way:
<custom-directive ng-model="parentObj.variable"></custom-directive>
I'm looking to extend an AngularStrap directive (typeahead in this case) to have more than the provided functionality. After some research, I'm thinking the best way is to wrap the typeahead directive with my own custom directive so that I can extend it.
I've followed all 3 suggestions found here for extending an Angular directive, but none of them seem to give me access to the typeahead controller and it's public functions.
Am I going about this the wrong way? What is the best way to extend the directives for custom functionality? Any help is greatly appreciated.
In my case, I followed the approach similar to the 2nd way described there.
The difference was to use 'require' to refer to the controller of the parent directive.
How to require a controller in an angularjs directive
If you look at the source of AngularStraps typeahead directive (Link) you'll see that it has two parts, the provider; '$typeahead' and the directive 'bsTypeahead'. What I've found in the past is easiest with this library is to copy the 'bsTypeahead' directive, rename it to something else then modify it's code to do as I want. The $typeahead provider acts like the controller in this case and all other AngularStrap directives work the same.
First, the best way is definitely to wrap the Angular Strap Directive in a Directive of your own. I've done this quite a bit with different Strap Directives. Secondly it's hard to say specifically what you need to do because you didn't name any specific goals. But if you look on the doc's for the Angular Strap project you'll notice various hints. In the case of typahead you have access to the $typeaheadProvider, also this is some what speculative on my part, but typeahead has a tooltip dependency so you may be able to use the $tooltip service to fiddle with typahead in your wrapper. Finally, the Angular Strap API for typeahead is pretty robust take another look at what is already available and you maybe able to accomplish what you want/need by working with what you've already got. I.E you can specify a custom template, or specify different prefix events which after taking another look at the docs myself seems to be an interface for interacting with the tooltip scope methods. I'm sorry this couldn't be more detailed on exactly what you need to do, but hopefully it will get you moving in the right direction.
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
ko.dataFor(element) allows to retrieve the object bound to a DOM element. Does angular have a similar function?
Maybe you can use:
angular.element(element1).scope().variable
element1: dom element,
variable: scope variable
More information here.
AngularJS have a different approach on that and data is not strictly bounded to DOM elements, You probably can look up for two way data binding that will bring you closer to the answer
Don't bind data to DOM elements in the first place. Store data in for example angular services.
I'm trying to use AngularJS to query the DOM of my view. I need to get all of the elements that have the attribute 'data-placement' with the value of 'top'. In jQuery, I would do this:
var elements = $('[data-placement="top"]');
However, I don't know how to do it with AngularJS. Can someone tell me how to do this?
Thank you!
In AngularJS you won't do direct DOM manipulation from the controller, you should create a directive to to that. Inside the directive you can use JQuery as you wish.
Anyway you I think you can use angular.element() with a JQlite selector, here's the documentation of angular.element.
Example:
// find('#id')
angular.element(document.querySelector('#id'))
From your question I understand that you wanted to find elements with atrributes requiring certain condition in that case we can use $document.
You can find more info about it here.
So coming to your requirement, you can find it by.
$document.find("[attribute-name='attribute-value')");
That will return the element object wrapped in jQuery or jqLite. But to use it you need to inject $document into your controller. So you continue angular related operations with it.
Another approach to this is angular.element.
angular.element.find("[attribute-name='attribute-value')");
But this will return element with wrapped raw DOM element or HTML string as a jQuery element. you can find more info about it here
I prefer to use $document as Angular operations can be done using the first method.