Situation: several developers working remotely on different section/modules of a SPA.
As a result they may accidentally introduce HTML elements with the same id
. W
If you are writing the same HTML code again and again with different IDs you are doing something wrong.
Nowadays, there are many ways of creating reusable HTML components that do not need IDs.
What I think is wrong:
For big projects (multiple teams involved or big amount of views) I don't think writting again and again raw HTML is a good idea.
That approach means: duplication of code and pain to refactor in the future (think about a restyle of the application in 2 years). That's why there are so many UI frameworks out there that help to create reusable components where HTML is written only once and used anywhere. At the end, your application will require a few components: table, popup, form, submenu, tabs..
The goal is to create a framework with those components that a developer can use to create a view without the need of actually writing any HTML code.
My point is: HTML code should be written once and only once in big projects. Obviously the fact that it's written once doesn't mean that it can only be rendered in one place, it can be anywhere in the application.
My suggestion:
Data-binding to the rescue!
If doing a big change is not possible, convention is the way to go. The one that you propose could make sense but be careful, every time that you change the structure all your IDs will be wrong!
Try to avoid using ID's except where absolutely necessary. When referencing HTML snippets from CSS or JS, stick to classes instead of IDs. Your CSS and JS shouldn't really care (separation of concerns) about the exact structure of the DOM or how many 'foo' elements are on the page... they just want to style or act on whatever 'foo' elements are there which classes are perfectly suitable for.
You can't avoid ID's entirely though... for example, marking up your HTML to support accessibility will require the use of IDs... but these IDs and references to them will be constrained to the same HTML file (or SPA template) so go ahead and make them verbose/lengthy to avoid conflicts if you feel a conflict is possible with any of them.
Of course this doesn't totally solve your problem. By focusing on classes you avoid the possibility of generating invalid HTML and everything blowing up but you still have the collaboration problem of making sure people aren't unexpectedly screwing up each other's work by using the same class names. In many cases, you'll actually want the same classes to be used across pages. In cases where you want to ensure there are no conflicts (for example, having common button or typography styles across the site), however, you could wrap each HTML template in something like <div class='name-of-this-template'>...</div>
and then in your CSS/JS selectors, scope the selector to only match within that template: .name-of-this-template .a-class-used-within-the-template
.
In one of my projects we got into this exact problem. Our quick solution and part of our next code maintenance/refactor cycle is to use identifiable html elements inherit the attributes of the JavaScript container with templates.
Let me go in more detail.
We use Backbone.Marionette
with Handlebars
templating. For each template we have a custom View class (we extended Backbone.Marionette with more features as we went on) associated to each template. This View class has an ID and UI elements. The UI elements are compiled in the template, therefore we never have to change the HTML unless we change the UI element name in the view class itself. Therefore, we can change our Id of the UI element however we want and won't affect anything (almost).
Since we use views for each widget, you can be sure their identifier or name or however you want to call it, is unique. We use that as a base for our Id's in our UI elements. This allows us Widget reuse.
_.uniqueId()
from the Underscore library is also used a lot for CollectionViews.
Hope I helped, cheers!
I would prefer to see ids used only to specify modules, widgets, main sections etc. This will lead less id's in general and most of your naming to be created by your business logic. You also end up structuring your classes & tags with a sort of localised hierarchy like: #specialWidget h3 {} #specialWidget p {}
and you just select your handlers like - $('#specialWidget .some-btn').click()
and never like $('#someBtn').click()
because it just get's messy and too specific.
Past that, testing and continuous integration are your best bet to catch things like this.
For instance, if developer X is developing a module Y, his prefix should be one of x_
, y_
or xy_
.
Assuming x_
was picked, IDs created by him would look like x_foo
, x_bar
, x_thing
etc.
Avoids colliding IDs (obviously).
While integrating modules, the IDs clearly indicate where they belong.
This provides improved readability, and that is pristine!!
Writing x_something
is irritating enough to avoid overindulgence in ID usage.
At the same time, it is not so irritating that no one will use them.
It'll make at least some developers unhappy. (Some are less flexible than others.)
A possible remedy is to ask them to change IDs to the x_
form,
only towards the end of development, just before integration.
Until then, they may use prefix-less ID names.
Some modules depend on other modules. Before integration,
appropriate ID names must be shared and correctly used.
While this may take some additional time, it would (hopefully) be worth it.
When a project is being developed in parallel by multiple teams the key factor in it's success is communication between the teams.
The teams should get together at set intervals to discuss cross-cutting concerns (e.g. naming strategies for ids). For instance if using the Scrum agile development methodology, the teams would meet periodically in a "Scrum of Scrums" meeting to discuss such an issue.
By having a conversation the teams will be able to agree on a naming convention (and document the agreed convention for future reference) which best suits the components being developed at that time (and when I say best at that time, I mean simplest and most easy to read whilst avoiding any naming clashes). Hence your suggestion to "pre-arrange" id's whilst work is being carried out in parallel isn't as ridiculous as you may think!