130

I am trying to find the element in html by angularjs.

Here is the html:

<button class="btn btn-primary multi-files" type="button">
   <span>Choose multiple files</span>
</button>
<br/><br/>
<input ng-file-select type="file" multiple  style="display: none"/><br/>

I am trying to get the button element by class name multi-files, then I tried

var multibutton = angular.element(element.getElementsByClassName(".multi-files"));

But it does not work, and tried element.find but it only works for tag.

Is there any function that can get element by id or classname in angularjs?

Tim
  • 41,901
  • 18
  • 127
  • 145
Justin
  • 2,765
  • 6
  • 24
  • 25
  • Maybe this helps: http://stackoverflow.com/questions/20801843/angularjs-find-element-with-attribute – Wim Deblauwe May 12 '14 at 12:35
  • You don't even have to create a directive.. you could simply add a handler like ng-click. Worst case, if you really want to get the element, you can always use jQuery syntax. – Lucas Holt May 12 '14 at 12:36

4 Answers4

192

getElementsByClassName is a function on the DOM Document. It is neither a jQuery nor a jqLite function.

Don't add the period before the class name when using it:

var result = document.getElementsByClassName("multi-files");

Wrap it in jqLite (or jQuery if jQuery is loaded before Angular):

var wrappedResult = angular.element(result);

If you want to select from the element in a directive's link function you need to access the DOM reference instead of the the jqLite reference - element[0] instead of element:

link: function (scope, element, attrs) {

  var elementResult = element[0].getElementsByClassName('multi-files');
}

Alternatively you can use the document.querySelector function (need the period here if selecting by class):

var queryResult = element[0].querySelector('.multi-files');
var wrappedQueryResult = angular.element(queryResult);

Demo: http://plnkr.co/edit/AOvO47ebEvrtpXeIzYOH?p=preview

tasseKATT
  • 38,470
  • 8
  • 84
  • 65
  • 1
    It may be worth noting that inside the link function, element.childElementCount may be 0 because angular hasn't had the chance to create the elements yet, so you should be prepared to deal with no results for element[0].getElement... – Dylanthepiguy Dec 21 '16 at 03:17
28

You don't have to add a . in getElementsByClassName, i.e.

var multibutton = angular.element(element.getElementsByClassName("multi-files"));

However, when using angular.element, you do have to use jquery style selectors:

angular.element('.multi-files');

should do the trick.

Also, from this 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.""

forresthopkinsa
  • 1,339
  • 1
  • 24
  • 29
Ashesh
  • 2,978
  • 4
  • 27
  • 47
  • hi, thanks for reply, i tried that, but error says undefined function – Justin May 12 '14 at 12:43
  • It might or might not work, yes. Please check my answer now (made an edit) and you'll probably know what to do. – Ashesh May 12 '14 at 12:44
  • If the function is undefined you probably didn't load jquery. jqlite (which is used if you didn't load jquery as @Ashesh mentioned) doesn't have all the functions that jquery has, and getElementsByClassName is one of them. – haimlit May 12 '14 at 13:10
  • 5
    angular.element('multi-files'); won't work. You do need the period. – Philippe Gioseffi Jan 25 '16 at 23:25
  • var multibutton = angular.element(document.getElementsByClassName("multi-files")); – Salman Lone Jul 04 '17 at 07:07
21

@tasseKATT's Answer is great, but if you don't want to make a directive, why not use $document?

.controller('ExampleController', ['$scope', '$document', function($scope, $document) {
  var dumb = function (id) {
  var queryResult = $document[0].getElementById(id)
  var wrappedID = angular.element(queryResult);
  return wrappedID;
};

PLUNKR

Ari
  • 1,595
  • 12
  • 20
-4

If you want to find the button only by its class name and using jQLite only, you can do like below:

var myListButton = $document.find('button').filter(function() {
    return angular.element(this).hasClass('multi-files');
});

Hope this helps. :)

Paul Rooney
  • 20,879
  • 9
  • 40
  • 61
  • 1
    This isn't using angular and jquery, also, incorrect statment, you CAN indeed use jquery to replace jqlite. This is the correct way to do this in an angular environment, without going down to the vanilla javascript element ($document[0]). – Dennis Bartlett Oct 27 '16 at 19:12