Browse Source

Implement linked_fields on ChooserViewSet

Matt Westcott 1 year ago
parent
commit
a3029bbe3a

+ 28 - 0
client/src/components/ChooserWidget/index.js

@@ -127,6 +127,34 @@ export class Chooser {
   }
 
   getModalOptions() {
+    const filters = {};
+    if (this.opts.linkedFields) {
+      for (const [param, lookup] of Object.entries(this.opts.linkedFields)) {
+        let val;
+        if (typeof lookup === 'string') {
+          val = document.querySelector(lookup).value;
+        } else if (lookup.id) {
+          val = document.getElementById(lookup.id).value;
+        } else if (lookup.selector) {
+          val = document.querySelector(lookup.selector).value;
+        } else if (lookup.match && this.chooserElement.id) {
+          const match = this.chooserElement.id.match(new RegExp(lookup.match));
+          if (match) {
+            let id = match[0];
+            if (lookup.append) {
+              id += lookup.append;
+            }
+            val = document.getElementById(id).value;
+          }
+        }
+        if (val) {
+          filters[param] = val;
+        }
+      }
+    }
+    if (Object.keys(filters).length) {
+      return { linkedFieldFilters: filters };
+    }
     return null;
   }
 

+ 3 - 0
client/src/includes/chooserModal.js

@@ -353,6 +353,9 @@ class ChooserModal {
     if (opts.multiple) {
       urlParams.multiple = 1;
     }
+    if (opts.linkedFieldFilters) {
+      Object.assign(urlParams, opts.linkedFieldFilters);
+    }
     return urlParams;
   }
 

+ 18 - 16
wagtail/admin/widgets/chooser.py

@@ -32,6 +32,7 @@ class BaseChooser(widgets.Input):
     classname = None
     model = None
     js_constructor = "Chooser"
+    linked_fields = {}
 
     # when looping over form fields, this one should appear in visible_fields, not hidden_fields
     # despite the underlying input being type="hidden"
@@ -39,21 +40,19 @@ class BaseChooser(widgets.Input):
     is_hidden = False
 
     def __init__(self, **kwargs):
-        # allow choose_one_text / choose_another_text to be overridden per-instance
-        if "choose_one_text" in kwargs:
-            self.choose_one_text = kwargs.pop("choose_one_text")
-        if "choose_another_text" in kwargs:
-            self.choose_another_text = kwargs.pop("choose_another_text")
-        if "clear_choice_text" in kwargs:
-            self.clear_choice_text = kwargs.pop("clear_choice_text")
-        if "link_to_chosen_text" in kwargs:
-            self.link_to_chosen_text = kwargs.pop("link_to_chosen_text")
-        if "show_edit_link" in kwargs:
-            self.show_edit_link = kwargs.pop("show_edit_link")
-        if "show_clear_link" in kwargs:
-            self.show_clear_link = kwargs.pop("show_clear_link")
-        if "icon" in kwargs:
-            self.icon = kwargs.pop("icon")
+        # allow attributes to be overridden by kwargs
+        for var in [
+            "choose_one_text",
+            "choose_another_text",
+            "clear_choice_text",
+            "link_to_chosen_text",
+            "show_edit_link",
+            "show_clear_link",
+            "icon",
+            "linked_fields",
+        ]:
+            if var in kwargs:
+                setattr(self, var, kwargs.pop(var))
         super().__init__(**kwargs)
 
     @cached_property
@@ -171,9 +170,12 @@ class BaseChooser(widgets.Input):
     def base_js_init_options(self):
         """The set of options to pass to the JS initialiser that are constant every time this widget
         instance is rendered (i.e. do not vary based on id / name / value)"""
-        return {
+        opts = {
             "modalUrl": self.get_chooser_modal_url(),
         }
+        if self.linked_fields:
+            opts["linkedFields"] = self.linked_fields
+        return opts
 
     def get_js_init_options(self, id_, name, value_data):
         return {**self.base_js_init_options}