From e8540fde8f75e71d9d6b2c389c74d5afba9ba24c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20P=C3=A9ters?= <fpeters@entrouvert.com>
Date: Mon, 6 Apr 2020 15:19:35 +0200
Subject: [PATCH] forms: pass extended options to custom live select fields
 (#41369)

---
 tests/test_form_pages.py             | 26 ++++++++++++++++++++++++++
 tests/utilities.py                   |  1 +
 wcs/fields.py                        |  7 +++++++
 wcs/forms/common.py                  |  8 ++++++--
 wcs/qommon/static/js/qommon.forms.js |  1 +
 5 files changed, 41 insertions(+), 2 deletions(-)

diff --git a/tests/test_form_pages.py b/tests/test_form_pages.py
index 4566f4587..10c4564b0 100644
--- a/tests/test_form_pages.py
+++ b/tests/test_form_pages.py
@@ -7013,6 +7013,32 @@ def test_field_live_select_content_on_other_default_select_option(pub, http_requ
     assert formdata.data['3'] == 'a'
 
 
+def test_field_live_select_extended_content(pub, http_requests):
+    FormDef.wipe()
+    formdef = FormDef()
+    formdef.name = 'Foo'
+    formdef.fields = [
+        fields.StringField(type='string', id='2', label='Bar2', size='40',
+            required=True, varname='bar2'),
+        fields.ItemField(type='item', id='3', label='Foo',
+            extra_css_class='template-whatever',
+            data_source={
+                'type': 'json',
+                'value': '{% if form_var_bar2 %}http://remote.example.net/json-list-extra?plop={{form_var_bar2}}{% endif %}'
+            }),
+    ]
+    formdef.store()
+    formdef.data_class().wipe()
+
+    app = get_app(pub)
+    resp = app.get('/foo/')
+    assert resp.html.find('div', {'data-field-id': '2'}).attrs['data-live-source'] == 'true'
+    assert resp.html.find('div', {'data-field-id': '3'}).find('select')
+    resp.form['f2'] = 'plop'
+    live_resp = app.post('/foo/live?modified_field_id=2', params=resp.form.submit_fields())
+    assert live_resp.json['result']['3']['items']['foo'] == 'bar'
+
+
 def test_field_live_comment_content(pub, http_requests):
     FormDef.wipe()
     formdef = FormDef()
diff --git a/tests/utilities.py b/tests/utilities.py
index 1616dfdcc..b725607ff 100644
--- a/tests/utilities.py
+++ b/tests/utilities.py
@@ -327,6 +327,7 @@ class HttpRequestsMocking(object):
             'http://remote.example.net/500': (500, 'internal server error', None),
             'http://remote.example.net/json': (200, '{"foo": "bar"}', None),
             'http://remote.example.net/json-list': (200, '{"data": [{"id": "a", "text": "b"}]}', None),
+            'http://remote.example.net/json-list-extra': (200, '{"data": [{"id": "a", "text": "b", "foo": "bar"}]}', None),
             'http://remote.example.net/json-err0': (200, '{"data": "foo", "err": 0}', None),
             'http://remote.example.net/json-err1': (200, '{"data": "", "err": 1}', None),
             'http://remote.example.net/json-list-err1': (200, '{"data": [{"id": "a", "text": "b"}], "err": 1}', None),
diff --git a/wcs/fields.py b/wcs/fields.py
index 6a0352c0f..71fc9d9d1 100644
--- a/wcs/fields.py
+++ b/wcs/fields.py
@@ -1425,6 +1425,13 @@ class ItemField(WidgetField):
             return [(x, x) for x in self.items]
         return []
 
+    def get_extended_options(self):
+        if self.data_source:
+            return data_sources.get_structured_items(self.data_source, mode='lazy')
+        if self.items:
+            return [{'id': x, 'text': x} for x in self.items]
+        return []
+
     def get_display_mode(self, data_source=None):
         if not data_source:
             data_source = data_sources.get_object(self.data_source)
diff --git a/wcs/forms/common.py b/wcs/forms/common.py
index de58c05f1..d08f54393 100644
--- a/wcs/forms/common.py
+++ b/wcs/forms/common.py
@@ -694,8 +694,12 @@ class FormStatusPage(Directory, FormTemplateMixin):
                     # was added to the form
                     result[field.id]['source_url'] = field.url
                 if modified_field_varnames.intersection(varnames):
-                    result[field.id]['items'] = [
-                            {'id': x[2], 'text': x[1]} for x in field.get_options(mode='lazy')]
+                    if 'template-' in (field.extra_css_class or ''):
+                        # custom template, it may need all option attributes
+                        result[field.id]['items'] = field.get_extended_options()
+                    else:
+                        result[field.id]['items'] = [
+                                {'id': x[2], 'text': x[1]} for x in field.get_options(mode='lazy')]
         for widget in form.widgets:
             if not getattr(widget, 'field', None):
                 continue
diff --git a/wcs/qommon/static/js/qommon.forms.js b/wcs/qommon/static/js/qommon.forms.js
index 9f9d07976..e0f60582e 100644
--- a/wcs/qommon/static/js/qommon.forms.js
+++ b/wcs/qommon/static/js/qommon.forms.js
@@ -118,6 +118,7 @@ $(function() {
               }
               $option.appendTo($select);
             }
+            $select.trigger('wcs:options-change', {items: value.items});
           }
           if (value.content) {
             var $widget = $('[data-field-id="' + key + '"]');
-- 
2.26.0

