hugo icon indicating copy to clipboard operation
hugo copied to clipboard

Featured request: Auto-ID helper function

Open earthboundkid opened this issue 5 years ago • 16 comments

For some things, HTML requires unique-per-page ids. For example, a <label for="xxx"> and <input id="xxx"> pair. If you have a partial for a form, you need each form on the page to have unique IDs. Right now, I'm solving this with a .Scratch variable that just sets a counter per page. It works, but it's a little awkward because you have to pass .Page into a shortcode that needs an ID, and if you do it wrong you can accidentally reset the counter.

I propose a template helper function called autoid that returns a new ID every time you call it. It could take a prefix argument to make the IDs prettier for developers. Could work like this:

<!-- root file -->
<h1>Try our form!</h1>
{{ partial "form.html" . }}

<h2>No, please, try our form!</h2>
{{ partial "form.html" . }}

<!-- form.html -->
<label for="{{ $emailID := autoid "myform" }}">Email</label>
<input id="{{ $emailID }}" name="email">
<label for="{{ $nameID := autoid "myform" }}">Name</label>
<input id="{{ $nameID }}" name="name">

<!-- output -->
<h1>Try our form!</h1>
<label for="myform-0001">Email</label>
<input id="myform-0001" name="email">
<label for="myform-0002">Name</label>
<input id="myform-0002" name="name">

<h2>No, please, try our form!</h2>
<label for="myform-0003">Email</label>
<input id="myform-0003" name="email">
<label for="myform-0004">Name</label>
<input id="myform-0004" name="name">

earthboundkid avatar Sep 25 '20 15:09 earthboundkid

This has been discussed before -- and the big problem of such function, if you make it something global, is that there is no way to preserve the ordering of things. And getting new IDs every time you run the site is not very friendly.

bep avatar Sep 25 '20 15:09 bep

I think that can just be documented. "IDs subject to change on each build." Maybe to make people less likely to rely on the ID being the same spit out some hex gibberish, like myform-1D4EAC. Really, it just sucks that HTML requires "unique" IDs, but I don't think I can open an issue with W3C to get them to change… 😄

earthboundkid avatar Sep 25 '20 15:09 earthboundkid

@carlmjohnson said:

It works, but it's a little awkward because you have to pass .Page into a shortcode that needs an ID, and if you do it wrong you can accidentally reset the counter.

Please explain the pain points. Why is your existing solution insufficient?

moorereason avatar Sep 26 '20 00:09 moorereason

I thought I had a working page, but it turned out I was passing the wrong context to a partial, so the counter had reset itself in the loop.

earthboundkid avatar Sep 26 '20 01:09 earthboundkid

https://github.com/spotlightpa/poor-richard/compare/de9720c54459f5bf6e26cd756b1edbb4d4bf9cc1...af7e3fc0d50df6f0d72fe33af83893d05812731f#diff-36cf9d21926ba6b11981f69cc4da1571 It got covered up by force pushes, but basically this dot needed to be a $ to fix a bug in a loop. It was sort of subtle.

earthboundkid avatar Sep 26 '20 01:09 earthboundkid

This issue has been automatically marked as stale because it has not had recent activity. The resources of the Hugo team are limited, and so we are asking for your help. If this is a bug and you can still reproduce this error on the master branch, please reply with all of the information you have about it in order to keep the issue open. If this is a feature request, and you feel that it is still relevant and valuable, please tell us why. This issue will automatically be closed in the near future if no further activity occurs. Thank you for all your contributions.

github-actions[bot] avatar Feb 19 '22 01:02 github-actions[bot]

This issue has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.

github-actions[bot] avatar Apr 02 '22 02:04 github-actions[bot]

I'll reopen this, because I find it better to write about these topics here rather than on the Discourse.

So, we already have math.Counter which I guess could be used to produce an ID ... but:

As you already experienced in https://discourse.gohugo.io/t/cachebuster-death-loop/45068/7 -- there are many reasons why you want this ID to be stable, for one, you would get massive change sets for your site on every build.

So, for most practical applications something like this should be OK:

{{ $pageIDString := .Page.RelPermalink | md5 }}
{{ $pageIDNumber := = .Page.RelPermalink | crypto.FNV32a  }}

bep avatar Jun 30 '23 07:06 bep

I don't see how making a hash of the page RelPermalink would address the problem at all. The issue to be solved is that I have form partials and I want to include that same partial an unknown number of times on one page. How does making up a semi-random ID once per URL address that?

earthboundkid avatar Jun 30 '23 13:06 earthboundkid

@carlmjohnson Are the forms included on the page via a shortcode that calls a form partial?

jmooring avatar Jun 30 '23 14:06 jmooring

Sometimes, yes. Also as plain partials.

earthboundkid avatar Jun 30 '23 14:06 earthboundkid

When inserted via shortcode, you can use .Ordinal (e.g., printf "foo-%03d" .Ordinal). The .Ordinal is stable from one build to the next.

jmooring avatar Jun 30 '23 15:06 jmooring

Another answer is to use Alpine's magic ID helper, but I'd rather not require JS for this functionality. https://alpinejs.dev/magics/id

earthboundkid avatar Jun 30 '23 15:06 earthboundkid

If you don't mind unstable id's, bep's suggestion of math.Counter works, and you can use that in base templates, partials, and shortcodes.

jmooring avatar Jun 30 '23 15:06 jmooring

I'm currently using a partial that adds one to a page.Store counter. It works but is apparently unstable.

earthboundkid avatar Jun 30 '23 16:06 earthboundkid

My only other thought for partials (you can use .Ordinal for shortcodes) is...

layout/_default/single.html (or whatever)

{{ partial "foo.html" (dict "page" . "id" "6" }}
...
{{ partial "foo.html" (dict "page" . "id" "7" }}

And change it each time you call it.

jmooring avatar Jun 30 '23 16:06 jmooring

This issue has been automatically marked as stale because it has not had recent activity. The resources of the Hugo team are limited, and so we are asking for your help. If this is a bug and you can still reproduce this error on the master branch, please reply with all of the information you have about it in order to keep the issue open. If this is a feature request, and you feel that it is still relevant and valuable, please tell us why. This issue will automatically be closed in the near future if no further activity occurs. Thank you for all your contributions.

github-actions[bot] avatar Aug 30 '25 02:08 github-actions[bot]

This issue has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.

github-actions[bot] avatar Nov 15 '25 02:11 github-actions[bot]