Find element without using angular.element and jQuery - angularjs

I have an Angular controller which uses pure Angular (no jQuery or Javascript). My problem is that I need to find and element without using jQuery or Javascript. I searched a lot on net but could not find any helpful answer.
The solution I found was to use angular.element, but it is not a good idea to use it.
Can anybody help me how to find element without using jquery.element or angular.element?
Thanks in advance.

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.
From here
PS: if you still want to use something other than this look here
Oh, one other edit: you can't actually use angular without javascript, since it is javascript framework..

I would recommend is to create a directive. The element is handed to you in the linking function:
link: function(scope, elem, attr) {
//elem is the dom element that contains the directive...your target object
}
If you do it like this you dont have to create a selector that would look at the entire dom from your controller. In your directive you could also do document.querySelector(".myclass") if the elem object doesn't work for your use case for whatever reason....but I think it should.

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.

For AngularJS Custom Directives, what is a correct way to find sub-elements in your template?

Say, if you define a directive with the template:
<div>
<button id="add-button">add</button>
{{ value }}
<button id="minus-button">minus</button>
</div>
Then what is a correct way to find your button in your link(scope, element, attrs) function?
Some thoughts and details:
I have seen
angular.element(document.getElementById("add-button"))
(the angular.element is just to convert it back to a jqLite/jQuery object)
but what if a user adds your directives multiple times on their page, then that line will find the wrong element because document.getElementById("add-button") will probably find the first matching element on the whole page with that ID.
Since jqLite can only find by tag name, so we may be able to do, by going back to DOM methods:
angular.element(element[0].querySelector("#add-button"))
Or, I don't know why jqLite doesn't let you find by class name or by ID, so it may be recommended to actually load jQuery before AngularJS, and use the full version of jQuery:
element.find("#add-button")
Or, supposedly only one element with the same ID should exist on the whole page, so to be more correct, we really should use class name instead of ID to identify the element, such as <button class="add-button"> and find it by
element.find(".add-button")
I think searching by tag name and then using the 1st found element or 2nd found element is not such a good way, because what if the template is changed or rearranged later, then you need to change your code too, so it is too tightly coupled together.
The most common way (seen by John Papa and Todd Motto) is to go with jqLite.
The worst way is using JQuery inside directives without restrictions.
Absolutly worst case:
$('.some-class')
Much better:
element.find('.some-class')
Also seen and valid:
$(element.find('.some-class'))
So, why you gonna do such things, manipulating DOM from a directive? There are a whole bunch of reasons. Maybe you want to initialize some JQuery plugins like datepicker or nanoscroller, then you need such things.
Styleguides are just philosphy, you can accept them, you just believe in small parts of the whole guide or you create your own. There are some guidelines out there, which can improve your code heavily (performance, readablity, etc.).
Styleguides
Angular 2 John Papa
Angular 1.x John Papa
Angular 1.x Todd Motto

AngularJS - Find Element by Attribute Value

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.

Angularjs directive : accessing sibling elements in link function

I've googled a lot to find an answer to a question which seems fundamental to me, but surprisingly with no success. The official doc left me without answers too.
So the simple question is : how to access sibling elements inside the link function of a directive ?
I have a view with an ng-repeat. My directive bind a click on each of the ng-repeat elements :
link: function (scope, element) {
element.bind('click', function () {
// how to access element.siblings here ?
...
Thanx.
If you are working with jQuery you can use the .siblings() function. If you only have an angular.element, you can access the subsequent siblings with the .next() function.
However, since you are using angularjs, I recommend to rely on the model for such kind of interactions instead of accessing DOM elements the "jQuery" way. If you provide more detail on what you are trying to do, somebody might suggest a better way (from a design perspective) to achieve your goal.

Creating an AngularJS Directive for jQuery UI Button

Update: Fiddle w/ full solution: http://jsfiddle.net/langdonx/VXBHG/
In efforts to compare and contrast KnockoutJS and AngularJS, I ran through the KnockoutJS interactive tutorial, and after each section, I'd rewrite it in AngularJS using what little I already knew + the AngularJS reference.
When I got to step 3 of the Creating custom bindings tutorial, I figured it would be a good time to get spun up on Angular Directives and write a custom tag. Then I failed miserably.
I'm up against two issues that I haven't been able to figure out. I created a new Fiddle to try and wrap my head around what was going on...
1 (fiddle): I figured out my scoping issue, but, is it possible to just passthrough ng-click? The only way I could get it to work is to rename it to jqb-click which is a little annoying.
2 (fiddle): As soon as I applied .button() to my element, things went weird. My guess is because both Angular and jQuery UI are manipulating the HTML. I wouldn't expect this, but Angular seems to be providing its own span for my button (see line 21 of the JavaScript), and of course so is jQuery UI, which I would expect. I hacked up the HTML to get it looking right, but even before that, none of the functionality works. I still have the scope issue, and there's no template binding. What am I missing?
I understand that there's an AngularUI project I should be taking a look at and I can probably pull off what I'm trying to do with just CSS, but at this point it's more about learning how to use Directives rather than thinking this is a good idea.
You can create an isolated scope in a directive by setting the scope parameter, or let it use the parent scope by not setting it.
Since you want the ng-click from parent scope it is likely easiest for this instance to use the parent scope within directive:
One trick is to use $timeout within a directive before maniplulatig the DOM within a templated directive to give the DOM time to repaint before the manipulation, otherwise it seems that the elements don't exist in time.
I used an attribute to pass the text in, rather than worrying about transclusion compiling. In this manner the expression will already have been compiled when the template is added and the link callback provides easy access to the attributes.
<jqbutton ng-click="test(3)" text="{{title}} 3"></jqbutton>
angular.module('Components', [])
.directive('jqbutton', function ($timeout) {
return {
restrict: 'E', // says that this directive is only for html elements
replace: true,
template: '<button></button>',
link: function (scope, element, attrs) {
// turn the button into a jQuery button
$timeout(function () {
/* set text from attribute of custom tag*/
element.text(attrs.text).button();
}, 10);/* very slight delay, even using "0" works*/
}
};
});
Demo: http://jsfiddle.net/gWjXc/8/
Directives are very powerful, but also have a bit of a learning curve. Also in comparison of angular to knockout, angular is more of a meta framework that in the long run has far more flexibilty than knockout
Very helpful reading for understanding scope in directives:
https://github.com/angular/angular.js/wiki/The-Nuances-of-Scope-Prototypal-Inheritance

Resources