如何在SurveyJS中根据前置问题答案设置Matrix Dynamic组件的固定行数
如何在SurveyJS中根据前置问题答案设置Matrix Dynamic组件的固定行数
我完全理解你的需求:希望用户先输入班级数量,再自动生成对应行数的矩阵表单,且不允许用户随意添加或删除行——这和Kobo Toolbox里按家庭成员数量生成行的逻辑完全一致。你直接用{num_classrooms}绑定属性的方式行不通,是因为SurveyJS的rowCount、minRowCount这类属性默认不会自动解析占位符,需要通过事件监听或者表达式绑定的方式来动态更新。
下面是两种可行的解决方案,其中事件监听的方式最直接且易维护:
方案一:通过onValueChanged事件动态更新行数
这是通用的实现方式,适用于所有SurveyJS运行环境(浏览器、React、Vue等)。核心思路是监听前置问题(num_classrooms)的值变化,实时同步更新矩阵的行数配置。
完整代码示例
<!-- 渲染Survey的页面容器 --> <div id="surveyContainer"></div> <script type="text/javascript"> const surveyJson = { "elements": [ { "type": "text", "name": "num_classrooms", "inputType": "number", "min": 1, "max": 20, "title": "How many classrooms do you teach in this school?", "isRequired": true }, { "type": "matrixdynamic", "name": "familyMatrix", "title": "Classroom Information", "columns": [ { "name": "name", "title": "Name", "cellType": "text" }, { "name": "age", "title": "Age", "cellType": "number" } ], // 初始设为0,后续通过事件动态更新 "rowCount": 0, "minRowCount": 0, "maxRowCount": 0 } ] }; // 创建Survey实例 const survey = new Survey.Model(surveyJson); // 监听问题值变化事件 survey.onValueChanged.add((sender, options) => { // 仅当变化的是班级数量问题时触发逻辑 if (options.question.name === "num_classrooms") { // 将用户输入的字符串转为整数,避免非数字值导致错误 const classCount = parseInt(options.value, 10); // 获取矩阵问题的实例 const matrixQuestion = sender.getQuestionByName("familyMatrix"); if (matrixQuestion && !isNaN(classCount) && classCount > 0) { // 统一设置行数配置,确保用户无法添加/删除行 matrixQuestion.rowCount = classCount; matrixQuestion.minRowCount = classCount; matrixQuestion.maxRowCount = classCount; // 刷新矩阵组件,让行数变化立即生效 matrixQuestion.render(); } } }); // 将Survey渲染到页面容器中 survey.render("surveyContainer"); </script>
代码逻辑说明
- 事件监听:通过
survey.onValueChanged捕获班级数量问题的数值变化; - 类型校验:把用户输入的字符串转为整数,过滤非数字输入的异常情况;
- 锁定行数:将矩阵的
rowCount、minRowCount、maxRowCount设为同一个值,彻底禁用行的增减操作; - 即时刷新:调用
render()方法确保行数变化立刻在页面上显示。
方案二:使用SurveyJS表达式绑定(进阶配置方式)
如果你更倾向于通过配置而非代码事件实现,可以利用SurveyJS的表达式功能。部分属性需要通过Expression后缀来启用动态绑定(不同版本的SurveyJS可能略有差异):
修改surveyJson中矩阵部分的配置:
{ "type": "matrixdynamic", "name": "familyMatrix", "title": "Classroom Information", "columns": [/* 你的列配置保持不变 */], // 用表达式绑定行数 "rowCountExpression": "{num_classrooms}", "minRowCountExpression": "{num_classrooms}", "maxRowCountExpression": "{num_classrooms}", // 禁用行增减按钮(可选) "allowAddRows": false, "allowRemoveRows": false }
注意事项
- 并非所有SurveyJS版本都支持
rowCountExpression这类属性,建议先在你的项目版本中测试; - 表达式使用SurveyJS原生语法,
{num_classrooms}会自动解析为对应问题的数值; - 搭配
allowAddRows和allowRemoveRows为false,可以完全锁定行的数量,避免用户误操作。
最终效果验证
两种方案都能实现你想要的流程:
- 用户首先输入1-20之间的班级数量;
- 输入完成后,矩阵自动生成对应数量的行;
- 用户只能逐行填写班级信息,无法修改行的数量,流程清晰直观。
这个实现完美匹配你提到的Kobo Toolbox式用户体验,先确定数量再填写详情,避免了用户操作的混乱。
内容来源于stack exchange




