6

I'm loading some HTML with jQuery asynchronously:

$.get(path, {}, function (data) {
    var result = $(data);
    var resultSelector = result.find(selector);
});

result is a valid HTML that contains my selector (in my specific case, "#UsersAndRolesResults").

I can see that it contains when I simply type result into the console, it's there exactly with the same ID, no typos or anything.

However, result.find(selector) returns 0 elements.

In my specific example, this is result:

enter image description here

And:

enter image description here

Why?

UPDATE: I can query for other elements that are inside #UsersAndRolesResults with their ID tag and they are returned correctly. I also cannot query any other top-level elements in the result. I think there is an issue with querying top-level elements inside the result.

UPDATE 2: Just try $('<div id="target"></div>').find("#target") and you will get 0 results, where you should obviously get the div.

8
  • If I'm reading this correctly, I think it's because the "result" is not yet part of the DOM. It hasn't been bound to anything. Commented Jun 26, 2016 at 3:28
  • @WonderGrub yes it's not added to DOM, and I can't add it to DOM as I need to grab only the element with that ID, and replace an element that already exists on the DOM with the same ID. I don't think it's a good idea to have two elements with the same ID simultaneously in the DOM. Commented Jun 26, 2016 at 3:32
  • Is result an entire document? Commented Jun 26, 2016 at 3:53
  • @guest271314 no, it's just part of a document Commented Jun 26, 2016 at 3:54
  • Can you reproduce at plnkr plnkr.co or jsfiddle jsfiddle.net? Commented Jun 26, 2016 at 3:55

4 Answers 4

6

No. This is not bug, this is behavior defined in jQuery.

find() is used to select the elements which are inside the element on which find is called. In your case, the element is not children of the selector, so find will not work.

Example:

<div id="container">
    <div class="message">Hello World!</div>
    <div>Bye World</div>
</div>

JavaScript:

$('#container').find('.message');

This will select the element having class message and which is inside the element having ID container.

But, if you use find, it'll return nothing i.e. empty array since there is no element #container inside #container.

$('#container').find('#container');

Your code is equivalent to this ^^^.


If you want, you can use filter. filter will go through each element and check if this matches the selector, if it then the element is added to the result set.

$('#container').filter('#container');

This'll give you complete element.

Sign up to request clarification or add additional context in comments.

8 Comments

Oh, I didn't know about filter. Great.
.closest() would return same result
@guest271314 NO. OP have a HTML code as string and want to get top level element like the example I've given.
@Tushar "NO. OP have a HTML code as string and want to get top level element like the example I've given." Actually, OP has not included what data is at original Question. Yes, .closest() would traverse both current selector, that is string wrapped in call to jQuery(), and return jQuery object representing selector if parameter to .closest() is selector within string passed to jQuery(), see stackoverflow.com/a/38035135
@CanPoyrazoğlu Can you add the HTML in question and do you always want to get top level element?
|
2

It seems to be a design decision with jQuery. Top-level elements in an AJAX result are not queried correctly with find. Interesting.

I've solved my problem with a workaround by creating a dummy div element, encapsulating my result inside that element, and then querying that dummy element. It worked:

var t = $("<div>")
t.append(result);
t.find("#UsersAndRolesResults"); //this one returned my object correctly

For a simple example, try:

$('<div id="target"></div>').find("#target");

You will get 0 results.

Try:

$('<div><div id="target"></div></div>').find("#target")

And you'll get the correct result.

13 Comments

Interesting, in my reduced case I wrapped my 2x <div /> elements in a parent container by default.
If I remove the wrapping element from the sample HTML data, I get 0 Nodes returned - a bug you have found.
"It seems to be a bug with jQuery" Can you include html string or array data at Answer? For ability to reproduce initially described issue, see stackoverflow.com/help/mcve
$('<div id="target"></div>').find("#target"); would not be expected to return #target; .find() searches for child elements
@guest271314 oh, then it's a design issue. anyway, I've updated my answer accordingly.
|
1

Try this:

$.get(path, {}, function (data) {
    var result = $($.parseHTML(data));
    var resultSelector = result.find(selector);
});

11 Comments

Nope, the result object is the same and still 0 results.
What is the real content of "path" ? I mean, in HTML.
I can't post the full HTML but it's exactly starting with what you see in the screenshot. Anyway, I've found the answer myself, see my answer.
I just reduced a test case and using this answer, I got the result you're after: imgur.com/BEi6W86 So I would qualify your input data.
@CanPoyrazoğlu yep, see my comment below :)
|
0

Given

console.log($("<div id=target></div>").find("#target"));
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

.length would be 0 as expected.


You can use .closest() to search for both child elements and original jQuery object selector

console.log($("<div id=target></div>").closest("#target"));
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

5 Comments

wouldn't filter be a better option (I've just learned it from another answer)? as travesing up a tree with closest would feel a bit awkward; I'm already querying the top-level element and it wouldn't make sense to traverse up, but it does make sense to travese down.
@CanPoyrazoğlu .closest() traverses current element; given .find() does not return expected result of query for an id, if element is in fact within document, could only be current selector or previous element within document
@Tushar "Tried to run second snippet in console, got this VM823:211 Uncaught DOMException: Failed to execute 'querySelector' on 'Document': '<div id=target></div>' is not a valid selector." Does not return that result, here. Have noticed stacksnippets freezing following addition of console. Will create a plnkr
Yes, that works :). Only problem I see is that it'll return only one element when used with general selector e.g. class selector. As you can see in question there are two elements having row class. So, $(thatHTMLString).closest('.row') will return .... Whereas filter will return all the elements having row class. CC @CanPoyrazoğlu
@Tushar OP appeared to be traversing for single element having an id, not multiple elements. though, again, still not certain what data is at OP? Image depicted does not appear to match description "result is a valid HTML that contains my selector (in my specific case, "#UsersAndRolesResults")." or example "<div id=target></div>", where image at OP displays elements before #UsersAndRolesResults? #UsersAndRolesResults : data` would not be <div id=UsersAndRolesResults></div>

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.