Address PR feedback

The slug generation logic required updates to support form prefixes like `quickadd`. Python-side changes
ensure `SlugField.get_bound_field()` updates the `slug-source` attribute to include the form prefix when
present, so JavaScript receives the correct prefixed field ID. `SlugWidget.__init__()` now adds a
`slug-field` class to enable selector-based field discovery. On the frontend, `reslug.ts` now uses class
selectors (`button.reslug` and `input.slug-field`) instead of ID-based lookups, eliminating the need for
fallback logic. The template was updated to use `class="reslug"` instead of `id="reslug"` on the button to
avoid ID duplication issues.
This commit is contained in:
Jason Novinger
2025-10-20 12:45:58 -05:00
parent 4e5db958c4
commit 2803b18699
6 changed files with 24 additions and 13 deletions

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -20,20 +20,15 @@ function slugify(slug: string, chars: number): string {
* For any slug fields, add event listeners to handle automatically generating slug values.
*/
export function initReslug(): void {
for (const slugButton of getElements<HTMLButtonElement>('button#reslug')) {
for (const slugButton of getElements<HTMLButtonElement>('button.reslug')) {
const form = slugButton.form;
if (form == null) continue;
// Try without prefix first, fallback to quickadd prefix for quick-add modals
const slugField = (form.querySelector('#id_slug') ??
form.querySelector('#id_quickadd-slug')) as HTMLInputElement;
const slugField = form.querySelector('input.slug-field') as HTMLInputElement;
if (slugField == null) continue;
const sourceId = slugField.getAttribute('slug-source');
// Try both patterns for source field as well
const sourceField = (form.querySelector(`#id_${sourceId}`) ??
form.querySelector(`#id_quickadd-${sourceId}`)) as HTMLInputElement;
const sourceField = form.querySelector(`#id_${sourceId}`) as HTMLInputElement;
const slugLengthAttr = slugField.getAttribute('maxlength');
let slugLength = 50;

View File

@@ -53,6 +53,14 @@ class SlugField(forms.SlugField):
self.widget.attrs['slug-source'] = slug_source
def get_bound_field(self, form, field_name):
if prefix := form.prefix:
slug_source = self.widget.attrs.get('slug-source')
if slug_source and not slug_source.startswith(f'{prefix}-'):
self.widget.attrs['slug-source'] = f"{prefix}-{slug_source}"
return super().get_bound_field(form, field_name)
class ColorField(forms.CharField):
"""

View File

@@ -56,6 +56,14 @@ class SlugWidget(forms.TextInput):
"""
template_name = 'widgets/sluginput.html'
def __init__(self, attrs=None):
local_attrs = {} if attrs is None else attrs.copy()
if 'class' in local_attrs:
local_attrs['class'] = f"{local_attrs['class']} slug-field"
else:
local_attrs['class'] = 'slug-field'
super().__init__(local_attrs)
class ArrayWidget(forms.Textarea):
"""

View File

@@ -19,7 +19,7 @@
{% if field|widget_type == 'slugwidget' %}
<div class="input-group">
{{ field }}
<button id="reslug" type="button" title="{% trans "Regenerate Slug" %}" class="btn">
<button type="button" title="{% trans "Regenerate Slug" %}" class="btn reslug">
<i class="mdi mdi-reload"></i>
</button>
</div>