Browse Source

Fixes #12145: Employ HTMXSelect widget to fix inclusion of <select> field values during form regeneration

jeremystretch 3 years ago
parent
commit
872b70c2b5

+ 1 - 0
docs/release-notes/version-3.5.md

@@ -78,6 +78,7 @@ Two new webhook trigger events have been introduced: `job_start` and `job_end`.
 * [#12112](https://github.com/netbox-community/netbox/issues/12112) - Do not link data source URL for local paths
 * [#12112](https://github.com/netbox-community/netbox/issues/12112) - Do not link data source URL for local paths
 * [#12115](https://github.com/netbox-community/netbox/issues/12115) - Fix rendering config templates from a data file
 * [#12115](https://github.com/netbox-community/netbox/issues/12115) - Fix rendering config templates from a data file
 * [#12144](https://github.com/netbox-community/netbox/issues/12144) - Ensure consistent treatment of context data when rendering config templates via UI & API
 * [#12144](https://github.com/netbox-community/netbox/issues/12144) - Ensure consistent treatment of context data when rendering config templates via UI & API
+* [#12145](https://github.com/netbox-community/netbox/issues/12145) - Employ `HTMXSelect` widget to fix inclusion of `<select>` field values during form regeneration
 * [#12146](https://github.com/netbox-community/netbox/issues/12146) - Do not display object selector for disabled fields
 * [#12146](https://github.com/netbox-community/netbox/issues/12146) - Do not display object selector for disabled fields
 
 
 ### Other Changes
 ### Other Changes

+ 2 - 7
netbox/core/forms/model_forms.py

@@ -7,6 +7,7 @@ from extras.forms.mixins import SyncedDataMixin
 from netbox.forms import NetBoxModelForm
 from netbox.forms import NetBoxModelForm
 from netbox.registry import registry
 from netbox.registry import registry
 from utilities.forms import CommentField, get_field_value
 from utilities.forms import CommentField, get_field_value
+from utilities.forms.widgets import HTMXSelect
 
 
 __all__ = (
 __all__ = (
     'DataSourceForm',
     'DataSourceForm',
@@ -23,13 +24,7 @@ class DataSourceForm(NetBoxModelForm):
             'name', 'type', 'source_url', 'enabled', 'description', 'comments', 'ignore_rules', 'tags',
             'name', 'type', 'source_url', 'enabled', 'description', 'comments', 'ignore_rules', 'tags',
         ]
         ]
         widgets = {
         widgets = {
-            'type': forms.Select(
-                attrs={
-                    'hx-get': '.',
-                    'hx-include': '#form_fields input',
-                    'hx-target': '#form_fields',
-                }
-            ),
+            'type': HTMXSelect(),
             'ignore_rules': forms.Textarea(
             'ignore_rules': forms.Textarea(
                 attrs={
                 attrs={
                     'rows': 5,
                     'rows': 5,

+ 4 - 10
netbox/dcim/forms/model_forms.py

@@ -12,10 +12,10 @@ from ipam.models import ASN, IPAddress, VLAN, VLANGroup, VRF
 from netbox.forms import NetBoxModelForm
 from netbox.forms import NetBoxModelForm
 from tenancy.forms import TenancyForm
 from tenancy.forms import TenancyForm
 from utilities.forms import (
 from utilities.forms import (
-    APISelect, add_blank_choice, BootstrapMixin, ClearableFileInput, CommentField, ContentTypeChoiceField,
-    DynamicModelChoiceField, DynamicModelMultipleChoiceField, JSONField, NumericArrayField, SelectWithPK,
-    SlugField, SelectSpeedWidget
+    add_blank_choice, BootstrapMixin, ClearableFileInput, CommentField, ContentTypeChoiceField,
+    DynamicModelChoiceField, DynamicModelMultipleChoiceField, JSONField, NumericArrayField, SlugField,
 )
 )
+from utilities.forms.widgets import APISelect, HTMXSelect, SelectSpeedWidget, SelectWithPK
 from virtualization.models import Cluster
 from virtualization.models import Cluster
 from wireless.models import WirelessLAN, WirelessLANGroup
 from wireless.models import WirelessLAN, WirelessLANGroup
 from .common import InterfaceCommonForm, ModuleCommonForm
 from .common import InterfaceCommonForm, ModuleCommonForm
@@ -1136,13 +1136,7 @@ class InterfaceForm(InterfaceCommonForm, ModularDeviceComponentForm):
         ]
         ]
         widgets = {
         widgets = {
             'speed': SelectSpeedWidget(),
             'speed': SelectSpeedWidget(),
-            'mode': forms.Select(
-                attrs={
-                    'hx-get': '.',
-                    'hx-include': '#form_fields input',
-                    'hx-target': '#form_fields',
-                }
-            ),
+            'mode': HTMXSelect(),
         }
         }
         labels = {
         labels = {
             'mode': '802.1Q Mode',
             'mode': '802.1Q Mode',

+ 17 - 0
netbox/utilities/forms/widgets.py

@@ -16,6 +16,7 @@ __all__ = (
     'ColorSelect',
     'ColorSelect',
     'DatePicker',
     'DatePicker',
     'DateTimePicker',
     'DateTimePicker',
+    'HTMXSelect',
     'MarkdownWidget',
     'MarkdownWidget',
     'NumericArrayField',
     'NumericArrayField',
     'SelectDurationWidget',
     'SelectDurationWidget',
@@ -293,3 +294,19 @@ class TimePicker(forms.TextInput):
         super().__init__(*args, **kwargs)
         super().__init__(*args, **kwargs)
         self.attrs['class'] = 'time-picker'
         self.attrs['class'] = 'time-picker'
         self.attrs['placeholder'] = 'hh:mm:ss'
         self.attrs['placeholder'] = 'hh:mm:ss'
+
+
+class HTMXSelect(forms.Select):
+    """
+    Selection widget that will re-generate the HTML form upon the selection of a new option.
+    """
+    def __init__(self, hx_url='.', hx_target_id='form_fields', attrs=None, **kwargs):
+        _attrs = {
+            'hx-get': hx_url,
+            'hx-include': f'#{hx_target_id}',
+            'hx-target': f'#{hx_target_id}',
+        }
+        if attrs:
+            _attrs.update(attrs)
+
+        super().__init__(attrs=_attrs, **kwargs)

+ 2 - 7
netbox/virtualization/forms/model_forms.py

@@ -12,6 +12,7 @@ from utilities.forms import (
     BootstrapMixin, CommentField, ConfirmationForm, DynamicModelChoiceField, DynamicModelMultipleChoiceField,
     BootstrapMixin, CommentField, ConfirmationForm, DynamicModelChoiceField, DynamicModelMultipleChoiceField,
     JSONField, SlugField,
     JSONField, SlugField,
 )
 )
+from utilities.forms.widgets import HTMXSelect
 from virtualization.models import *
 from virtualization.models import *
 
 
 __all__ = (
 __all__ = (
@@ -318,13 +319,7 @@ class VMInterfaceForm(InterfaceCommonForm, NetBoxModelForm):
             'mode': '802.1Q Mode',
             'mode': '802.1Q Mode',
         }
         }
         widgets = {
         widgets = {
-            'mode': forms.Select(
-                attrs={
-                    'hx-get': '.',
-                    'hx-include': '#form_fields input',
-                    'hx-target': '#form_fields',
-                }
-            ),
+            'mode': HTMXSelect(),
         }
         }
 
 
     def __init__(self, *args, **kwargs):
     def __init__(self, *args, **kwargs):