Loading jquery is must in angularjs? - angularjs

Am trying to manipulate dom by using jquery in angularjs; As per the documentation
"If jQuery is available, angular.element is an alias for the jQuery function.
If jQuery is not available, angular.element delegates to Angular's built-in subset of jQuery, called "jQuery lite" or "jqLite."
I have two links one using jquery works and one without using jquery throws error.
Needed some suggestion on how to get this working without declaring jquery externally?

I don't think Angular's jQlite supports the .focus() shortcut - jQlite is only a subset of jQuery see https://docs.angularjs.org/api/ng/function/angular.element for a list of jQlite methods.
You need to call focus on element[0].focus as per this stackoverflow answer HTML5: How to set focus on a text input in a list with AngularJS

You can read here the methods that jqLite provide.
In this particular case you could write something like this.
var app = angular.module("myapp", []);
app.controller('myappCtrl', function($scope,$timeout) {
$timeout(function() {
document.getElementById('number').focus()
}, 1);
angular.element(document.getElementById('focusguard-2')).on('focus', function() {
document.getElementById('number').focus();
});
angular.element(document.getElementById('focusguard-1')).on('focus', function() {
document.getElementById('cancel').focus()
});
});

Related

Angular JS manipulating dom by element from link function

we know that we can access dom from directive by element because element is injected in link function.
see the approach
var app = angular.module("myApp", []);
app.directive('busyBox',function(){
return {
restrict: 'A',
link: function(scope, element, attrs) {
element.on('click', function(){
if(attrs.id=='btnadd')
{
var divElement = angular.element(document.body.querySelector('.parent')).append('<div class="child">Some text</div>');
// console.log(divElement);
// element.parent().find('.parent').append('<div>Some text</div>')
//element.closest('.parent').append('<div class="child">child</div>')
//angular.element(document).find('.parent').append('<div class="child">child</div>');
}
else if(attrs.id=='btnDel')
{
angular.element(document.body.querySelector('.child')).remove();
// m.removeChild(m.firstChild);
}
});
}
}
})
the above code is working but if i do not use angular.element() instead if i use element(document.body.querySelector('.parent')) the code is not working.
the element is injected in link function link: function(scope, element, attrs)
when element is there in directive then why should i use angular.element() ?
please tell me how could i use element from directive to access dom instead of angular.element().
thanks
The element exposed to the postLink function is a jqLite class object which is a tiny, API-compatible subset of jQuery that allows AngularJS to manipulate the DOM in a cross-browser compatible way. jqLite implements only the most commonly needed functionality with the goal of having a very small footprint.
The find() method is limited to lookups by tag name. If you want the find() method to work with class selectors, load jQuery before the angular.js file.
If jQuery is available, angular.element is an alias for the jQuery function. If jQuery is not available, angular.element delegates to AngularJS's built-in subset of jQuery, called "jQuery lite" or jqLite.
To use jQuery, simply ensure it is loaded before the angular.js file. You can also use the ngJq directive to specify that jqlite should be used over jQuery, or to use a specific version of jQuery if multiple versions exist on the page.
— AngularJS angular.element API Reference
Can't we use element. closest function instead of find to get the div?
The jQuery closest function is not part of AngularJS jqLite. To use the closest function with the element value exposed to the directive postLink function, load the jQuery library before loading the AngularJS library.
For the list of jqLite functions, see AngularJS angular.element API Reference
please tell me how could i use element from directive to access dom instead of angular.element()
If you want to use the element object that is passed into the link function of the directive to manipulate the DOM, you have to use various methods that the element object exposes, like find.
Do not use it like this:
element(document.body.querySelector('.parent'))
Instead you can do:
// works only if you are using jQuery
element.find('.parent');
// for JQLite, the find method is limited to lookup by tag name:
element.find('div');
Note that as mentioned in the answer from #georgeawg, that you might be using JQLite or JQuery ... where the JQLite functionality is not as full featured as JQuery.

correct way to get data attribute into scope value

So with regular jquery, I can do:
var = variable.data('data-attribute');
What would be the correct way to do this with Angular?
There are various ways to do this, you should even use the jQuery command that you wrote above to read data attribute. Do this inside a controller and you are OK. I used jQuery for readability sake, you should use jQueryLite or even Vanilla Javascript.
In your controller:
app.controller('MainCtrl', function($scope) {
$scope.name = 'World';
$scope.expando = $( "#testId" ).data( "test" );
});
and in your view:
<p id="testId" data-test="this is expando attr">Hello {{name}}, {{expando}}!</p>
See the plunker for example.
This hovewer (maybe) is not the best solution! More suitable should be the use of a directive. Probably that attribute is something that you read inside a Javascript function to do something with the DOM, and the directives are the angular way to reuse component that alter the DOM.
So, your question can't have a better answer until you don't specify what's the use of that data-attribute.

jQuery element initialization in Angular

I'm learning AngularJs and I'm playing with a third party Javascript component.
At a certain point the control is initialized as follows:
$(document).ready(function () {
$('#SomeId').initialize();
});
Is there a way to convert this to something more Angularish? I don't want to manipulate the DOM from the controller, but I'm not sure how to initialize this.
This code is not necessarily wrong as is. What you want to be careful about is javascript outside of the angular context (jQuery callbacks/plugins etc) manipulating $scope values because those functions will not trigger an angular digest loop, and will result in a disconnect between the DOM and the $scope.
Here is some more information about this cycle and what you need to know about it: http://jimhoskins.com/2012/12/17/angularjs-and-apply.html
Here is a common use case with jQuery (and also why you should try to use angular services (ie: $http) instead:
// When you manipulate the $scope with a non-angular callback,
// you have to run $scope.$apply() to tell angular about the
// change in order to repaint the DOM
$.get( "/getUser", function( data ) {
$scope.user = data; // set $scope data in callback
$scope.$apply(); // run digest so anything in the DOM binded to the {{user}} model gets updated
});
Generally you don't need to manipulate the DOM like this with Angular...so you really don't need jQuery. Using an Angular "directive" is the declarative, encapsulated way to do it in Angular. There are a ton of 3rd party components out there for you to use that have been built properly with directives: I would recommend using these rather than trying to convert a jQuery plugin (which is really just adding the jQuery bloat for things that you already have access to with Angular). A good place to start looking for Angular directives that you can use is http://ngmodules.org/

Angular directive doesn't work for elements added to the DOM by jquery plugin

I'm creating a fall back image directive that looks like this http://plnkr.co/edit/wxy4Sp2K02iXoQNsvkah
angular.module('directives').directive('myDirective', function() {
return {
restrict: 'C',
link: function(scope, element, attrs) {
console.log('linking');
}
}
});
My directive doesn't work for elements that are added to the DOM by the typeahead.js plugin (https://github.com/twitter/typeahead.js).
<div class='tt-suggestion'>
<div><span class="my-directive">bla</span></div>
</div>
I guess it's because Angular is not informed about the elements that are added by jQuery and hence it doesn't invoke the directive. How do I notify Angular of these changes?
You can use the Angular compile service to do this: http://docs.angularjs.org/api/ng/service/$compile
Basicly it works like this:
document.getElementById("test").innerHTML = $compile("")($scope);
ideally you shouldnt be mixing jquery and angular because they both are based on different philosophy.
jquery-- is event driven i.e. have event listeners which cause changes to model and then the programmer has to code numerous lines to change the view i.e. changing css,text etc
angular-- woo hoo! just change the model which is binded to $scope and :) your view is automatically updated
to automatically react on changing of such events angular has a compiler which studies entire html code before the app is loaded so even if there is a template which you might use later you must enclose it in so that angular compiles this so that all the special angular directive and controller perform as expected even when you remove or add templates to the dom.
here you are using typehead.js and jquery to manually manipulate the view which is against angular philosophy because when you do such maipulation angular compiler wouldnt be aware of it as it runs only when the app is initialized. Thats why before appending you should use $compile to make the angular compiler aware of this template .
in your case i would suggest the typehead present on this url
http://angular-ui.github.io/bootstrap/

What is meant by AngularJS element?

I am trying to learn AngularJS. I was reading the https://github.com/angular/angular.js/wiki/Understanding-Directives : "You do NOT have to wrap AngularJS elements in jQuery()"
What is meant by an AngularJS element?
In Jquery, if I have a DOM element, say by using document.getElementByID() and if I want to make it a jquery element with access to all of its awesome functions, I will simply say
var domElement = document.getElementByID("elemID");
var $domElement = $(domElement); (To cache the element)
So, if in angular I dont have to wrap the DOM element as in Jquery, then can I simply query the DOM and access it and still be able to access all the angular methods.
If so, how it is done? Is it because of the ng-app binding?
Are all DOM elements inside ng-app internally accessed by Angular and turned to equivalent AngularJS elements?
The wiki page is talking about the elements passed by Angular as arguments to the compile and link functions of the directive:
link: function LinkingFunction($scope, $element, $attributes) { ... }
^-- here
If you get an element from the DOM using document.getElementById(), it won't be wrapped in jQuery automatically.

Resources