如何在Docassemble中通过Ajax/JS动态联动countries_list与states_list?
在Docassemble中实现国家-地区实时联动(同一页面)
核心实现思路
- 用
input type: ajax定义国家选择框,绑定前端JS触发事件 - 通过自定义JS监听国家选择变化,向Docassemble后端请求对应地区列表和
subdivision_type值 - 实时更新地区下拉框的选项、标签文本,同时处理单一地区国家的自动填充/隐藏逻辑
完整代码实现
1. Docassemble YAML 配置
question: | 请选择您所在的国家和地区 fields: - 国家: user_country input type: ajax choices: countries_list() js: | $(this).on('change', function() { updateSubdivisions($(this).val()); }); - id: subdivision_field 地区: user_subdivision input type: select choices: [] skip: True # 初始隐藏,后续根据AJAX结果控制显示 comment: | <script> function updateSubdivisions(countryCode) { // 发送AJAX请求获取地区数据 $.ajax({ url: '/api/questions', method: 'POST', data: JSON.stringify({ "action": "get_subdivisions", "country": countryCode }), contentType: 'application/json', success: function(response) { const subdivisionField = $('#subdivision_field'); const subdivisionLabel = subdivisionField.prev('label'); const subdivisionSelect = subdivisionField.find('select'); // 更新地区标签文本(如省/州/地区) subdivisionLabel.text(response.subdivision_type + ':'); // 清空并填充地区选项 subdivisionSelect.empty(); response.subdivisions.forEach(function(option) { subdivisionSelect.append($('<option>', { value: option.code, text: option.name })); }); // 处理单一地区的情况:自动选中并隐藏字段 if (response.subdivisions.length === 1) { subdivisionSelect.val(response.subdivisions[0].code); // 自动提交选中值到后端 $.ajax({ url: '/api/set', method: 'POST', data: JSON.stringify({ "user_subdivision": response.subdivisions[0].code }), contentType: 'application/json' }); subdivisionField.parent().hide(); } else { subdivisionField.parent().show(); subdivision_field.set('skip', false); // 取消跳过,让系统验证该字段 } }, error: function() { alert('获取地区信息失败,请重试'); } }); } </script> # 后端AJAX处理逻辑 code: | from docassemble.base.util import states_list, subdivision_type import json def get_subdivisions(country): subdivisions = states_list(country) # 转换为前端可用的格式 formatted_subdivisions = [{'code': code, 'name': name} for code, name in subdivisions.items()] return { 'subdivision_type': subdivision_type(country), 'subdivisions': formatted_subdivisions } # 处理AJAX请求 if request.method == 'POST' and 'action' in request.json and request.json['action'] == 'get_subdivisions': country_code = request.json.get('country') result = get_subdivisions(country_code) return json.dumps(result)
2. 关键细节说明
- AJAX接口利用:通过Docassemble内置的
/api/questions获取地区数据,/api/set提交选中的地区值到后端 - 动态标签更新:直接修改页面上的标签元素文本,实时替换为
subdivision_type()返回的对应地区类型名称 - 单一地区自动处理:检测到地区列表长度为1时,自动选中该选项并隐藏下拉框,无需用户手动操作
- 初始状态控制:地区字段初始设置
skip: True,避免页面加载时显示空的下拉框
注意事项
- 确保Docassemble项目默认的AJAX功能处于开启状态
- 测试时需验证不同国家的地区数据返回准确性,尤其是单一地区的国家
- 若需调整样式,可通过CSS自定义字段的显示/隐藏效果
内容的提问来源于stack exchange,提问作者NotAnAmbiTurner
相关产品推荐
相关产品推荐

