I was trying to help someone with no coding experience create a Netlify form. Netlify has a good free platform for processing HTML forms (Form submissions | Netlify Docs), but I couldn’t find a good no-code open-source solution to build one. Panel is like a sonic screwdriver that even works on wood, so I just opened the lock. Output of the code below is here: https://riziles.github.io/PanelForm/panel_form.html
import yaml
import panel as pn
pn.extension()
template = """
{% extends base %}
<!-- goes in body -->
{% block contents %}
<div class="container">
<div class="row">
<div class="col-sm">
{{ embed(roots.A) }}
</div>
<form name="contact" method="POST" data-netlify="true" id = "q"></form>
</div>
</div>
{% endblock %}
"""
yaml_str = """
What is the capital of Djibouti?:
- ( ) option 1
- ( ) option 2
Check all that apply:
- x option 1
- x option 2
What's your name?: _______
"""
def parse_yaml_form(yaml_str:str) -> pn.Column:
yaml_str_clean = yaml_str.replace('[ ]','x ')
dic = yaml.load(yaml_str_clean, yaml.CLoader)
widgets = {}
counter = 0
json_str = '{'
out = []
for key1, val1 in dic.items():
if isinstance(val1,list) and all([i[:3] == '( )' for i in val1]):
widgets['input' + str(counter)] = pn.widgets.RadioBoxGroup(
name=key1,
options = [i[3:] for i in val1],
value = ""
)
js_param = 'active'
elif isinstance(val1,list) and all([i[:2] == 'x ' for i in val1]):
widgets['input' + str(counter)] = pn.widgets.CheckBoxGroup(
name=key1,
options = [i[2:] for i in val1],
value = []
)
js_param = 'active'
elif isinstance(val1,str) and val1[:3] == '___':
widgets['input' + str(counter)] = pn.widgets.TextInput(
name=''
)
js_param = 'value'
out.append(key1)
out.append(widgets['input' + str(counter)])
json_str += f'input{str(counter)}_val:input{str(counter)}.{js_param},'
counter += 1
json_str += '}'
button = pn.widgets.Button(name = 'button')
out.append(button)
h = pn.pane.HTML('''
<form id="q" data-netlify="true">
</form>
''',
height = 100)
# out.append(h)
# widgets['h'] = h
button.jscallback(
clicks = f'''
let data = JSON.stringify({json_str});
let exists = document.getElementById("submission");
if(exists){{exists.remove()}};
let textarea = document.createElement("textarea");
textarea.id = "submission"
textarea.cols = "60";
textarea.textContent = data;
document.getElementById("q").appendChild(textarea)
// textarea.style.visibility = "hidden"
// document.getElementById("q").requestSubmit()
''',
args=widgets
)
form = pn.Template(template)
form.add_panel('A', pn.Column(*out))
return form
out = parse_yaml_form(yaml_str)
out.save('panel_form.html')