1

I dynamically clone an element using jQuery and ask an object to return its length, but it returns 1 every time. Please see fiddle:

https://jsfiddle.net/gatzkerob/x5xd2x7q/3/

<span class="count">0</span>
<br>
<button>click</button>
<br>
<span class="a">a</span>

var obj = {
elem : $('.a')
}

function cloneThisAndCount(){
$('.a').last().after($('.a').first().clone());
$('.count').text(obj.elem.length);
}

$('button').click(function(){
cloneThisAndCount();
});
7
  • use $('.count').text($('.a').length); Commented Jul 29, 2016 at 3:21
  • 1
    What is expected result? Commented Jul 29, 2016 at 3:34
  • 1
    Please edit your question to show the relevant code directly in the question body. (As far as your actual problem, nothing in your code updates the obj object after it is created.) Commented Jul 29, 2016 at 3:36
  • He just doesn't know that the selector result is caching to the property Commented Jul 29, 2016 at 3:37
  • I know that I can access directly using $('.a') but I want to use properties so I don't have to type long class names every time. Commented Jul 29, 2016 at 3:39

1 Answer 1

2
var obj = {
  elem : $('.a')
}

will be computed once and cached into obj.elem in the begenning. which will be 1.

Note (thanx to nnnnn): When you have a reference to a jQuery object it is possible that other code could update that object to add more elements to it.

SOLUTION 1:

What you need is to do is, redo the selector every time before calculating length.

function cloneThisAndCount() {
  $('.a').last().after($('.a').first().clone());
  $('.count').text($('.a').length);
}

$('button').click(function() {
  cloneThisAndCount();
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<span class="count">0</span>
<br>
<button>click</button>
<br>
<span class="a">a</span>

SOLUTION 2:

Change obj to:

var obj = {
  elem : function(){ return $('.a')}
}

and then check length like: $('.count').text(obj.elem().length);

var obj = {
  elem: function() {
    return $('.a')
  }
}

function cloneThisAndCount() {
  $('.a').last().after($('.a').first().clone());
  $('.count').text(obj.elem().length);
}

$('button').click(function() {
  cloneThisAndCount();
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<span class="count">0</span>
<br>
<button>click</button>
<br>
<span class="a">a</span>

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

10 Comments

Snippet #2 did the trick, cheers. I actually tried that at one stage but didn't add parenthesis after "elem".
"which will be 1." - Note that when you have a reference to a jQuery object it is possible that other code could update that object to add more elements to it. (But as you've said, it doesn't automatically update itself to include elements later added to the DOM.)
Cool. Of course (as usual) I'm being overly pedantic, because the vast majority of jQuery methods return a new object without changing the old one so 99% of the time it's not a problem, but there are ways to change an existing jQuery object, e.g., $.merge(obj.elem, $("p")).
is there any reason for the behaviour?
some being updated, while others don't . - Assuming in the merge example $('p') was updated.
|

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.