Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

With Meteor, why should DOM manipulation NEVER be done with jQuery?

Tags:

jquery

meteor

I'm curious about the validity of this statement:

A good rule of thumb is that if you're using jQuery to manipulate any DOM elements, you're probably doing it wrong.

from the answer to this question: Meteor - How can I pass data between helpers and events for a template?

The way I see it, jQuery is good because it can be surgical and manipulate many small parts of the DOM without having to change an entire code block.

Templates in Meteor are great because that's precisely what they do - they can swap out entire code blocks or small tiny things for something else, but at the expensive of having to define it explicitly every time and redefining code that actually doesn't change.

Example - on focus, jQuery removes the idleField class, adds the focusField class, and changes the placeholder to some other text:

<input class="idleField" id="first_name" name="firstName" type="text" placeholder="First Name" maxlength="10"/>

$('input[type="text"]').focus(function() {
  $(this).removeClass("idleField").addClass("focusField").attr("placeholder", "First Name NOW");
});

The result is

<input class="focusField" id="first_name" name="firstName" type="text" placeholder="First Name NOW" maxlength="10"/>

The jQuery is short and sweet and targeted just at toggling the class and placeholder.

But with Meteor templates, the same result would be something like:

<input {{toggleClassAndEditPlaceholder}} maxlength="10"/>

Session.set('toggleClassEditPlaceholderSessionVar', ' class="idleField" id="first_name" name="firstName" type="text" placeholder="First Name" ');

Template.form.helpers({
  toggleClassAndEditPlaceholder: function() {
    return Session.get('toggleClassEditPlaceholderSessionVar');
)};

Template.form.events({
  'focus input[type="text"]': function () {
    Session.set('toggleClassEditPlaceholderSessionVar', ' class="focusField" id="first_name" name="firstName" type="text" placeholder="First Name NOW" ');
  }
});

The Meteor way is a lot more verbose and at least in this example, includes redundant items ( id, name, and type don't change, only class and placeholder). jQuery targeted ONLY the class and placeholder and left everything else alone. Templates, however, sometimes have to encompass a lot of extraneous stuff. In this example, sure, I could have moved placeholder and class side by side in my code so that id, name, and type are untouched when defining the template, but in some other code you wouldn't be able to.

So what am I doing wrong? Is there supposed to be a much more efficient way of doing it in Meteor, one that's more efficient that just that single jQuery line?

like image 701
fuzzybabybunny Avatar asked May 29 '14 13:05

fuzzybabybunny


People also ask

Should I use DOM or jQuery?

In an ideal situation you don't need jQuery, your better off using the real DOM API and using polyfills for browser compliance. Knowing and using the real DOM API increases readability/maintainability because all web developers know the DOM and only some know library X.

Can DOM be manipulated without JavaScript?

For manipulating DOM you need a scripting language like JS, VB etc.

Is DOM manipulation important?

DOM manipulation is an important factor while creating a web application using HTML and JavaScript. In this article, we will be learning about what is DOM (Document Object Model) and how to use it along with its features and functions using JavaScript and HTML.

What is DOM manipulation in JavaScript?

In website development, DOM stands for Document Object Model. It is a programming interface that allows us to create, change, or remove elements from a website document. DOM manipulation is when you use JavaScript to add, remove, and modify elements of a website. It is very common in web development.


2 Answers

The statement in question was made nine months ago. It was very important at that time. Since then Meteor UI engine received a complete overhaul. One of key points of that change was to make the engine more JQuery-friendly. Before, when you changed with JQuery, chances were Meteor would revert that change on redraw. Now it makes its changes in much more clever way, so it's safe to alter the elements state with pure JQuery.

That being said, it's still a good practice to think carefully whether the change you're going to need is really better done with JQuery. Specifically, it's better to leave all data-related changes to Meteor. In your case, however, you alter the behavior of a UI component based purely on its state. So indeed, to make that change with Meteor alone you'd need to create an artificial data object, and indeed, it's better to just use JQuery in this case.

 


 

Aside from that, your Meteor code itself can be significantly improved. You don't need to pass all tag attributes in the helper, it's enough to change the thing you need:

<input id="..." type="..." name="..." class="{{class}}" placeholder="{{placeholder}} maxlength="10"/>

Template.form.helpers({
  class: function() {
    return Session.get('toggled') ? 'focusField' : 'idleField';
  },
  placeholder: function() {
    return Session.get('toggled') ? 'focusPlaceholder' : 'idlePlaceholder';
  },
)};

Template.form.events({
  'focus input[type="text"]': function () {
    Session.set('toggled', true);
  },
});
like image 130
Hubert OG Avatar answered Sep 28 '22 14:09

Hubert OG


First, the original SO post you cite was referencing using jQuery for "reactive" data changes (on model data) and the answer was pointing the author toward using the Collection API to avoid having to manually update the DOM. When you pull data from a Meteor.Collection and display it on the page, you are using a "reactive" data source...updates will happen automagically.

Your example doesn't really follow the same reasoning. Therefore, you would most definitely make use of jQuery to simplify your approach. It would look something like:

Template.form.events({
  'focus input[type="text"]': function (e) {
      $(e.currentTarget).removeClass("idleField").addClass("focusField").attr("placeholder", "First Name NOW");
  }
});

There's no reason to litter the global Session object with a bunch of key/value pairs for element attributes. Even if you did, there's no reason to store the attributes that remain the same (id, name, type).

like image 24
fletch Avatar answered Sep 28 '22 16:09

fletch