`

JSON 级联表单

    博客分类:
  • AJAX
 
阅读更多

动态下拉列表的原理其实很简单的,当某一下拉列表触发了onchange事件,然后使用AJAX在后台向服务器异步请求数据,最后将服务器返回的数据进行解析后动态添加到指定的select上即可!

    首先来看后台的数据输出,我们假设服务器传送给客户段的JSON数据格式为如下:

{
    "options" : [
        {"value" : 值,"text" : 文本}, 
        {"value" : 值,"text" : 文本},
        {"value" : 值,"text" : 文本}
        ]
}

    其中options是整个JSON对象的标识符,它是一个数组,该数组中的每一个值表示一个select中的option,当然该值也是一个对象了,有两个属性,一个是value,一个是text,分别对应option中的value和显示的text值。

    有了数据格式,那么客户端和服务器端进行交流就方便很多了。我们来先写客户端的JS方法。这里我是提供一个静态的实用类Select,专门针对select元素的操作方法,如下:

/**-----------------------------------------------------------------------
 * ------------------------针对select操作的实用Select类-------------------
 * -----------------------------------------------------------------------
 */
function Select(){};
/**
 * 根据指定的JSON对象来生成指定的select的options项(清除原来的options).
 */
Select.create = function(/*string*/selectId,/*json object*/json) {
 Select.clear(selectId);
 Select.add(selectId, json);
};
/**
 * 该方法同create,只不过是在原来的基础上进行追加
 */
Select.add = function(/*string*/selectId,/*json object*/json) {
 try {
  if (!json.options) return;
  for (var i = 0; i < json.options.length; i ++) {
   Select.addOption(selectId,json.options[i].value,json.options[i].text);
  }
 } catch (ex) {
  base.alert('设置select错误:指定的JSON对象不符合Select对象的解析要求!');
 }
};
/**
 * 创建一个options并返回
 */
Select.createOption = function(/*string*/value, /*string*/text) {
 var opt = document.createElement('option');
 opt.setAttribute('value', value);
 opt.innerHTML = text;
 return opt;
};
/**
 * 给指定的select添加一个option,并返回当前option对象
 */
Select.addOption = function(/*string*/selectId, /*string*/value, /*string*/text) {
 var opt = Select.createOption(value, text);
 $(selectId).appendChild(opt);
 return opt;
};
/**
 * 获取指定select的当前被选中的options对象,如果为多选且有多个被选中则返回数组.
 */
Select.getSelected = function(/*string*/selectId) {
 var slt = $(selectId);
 if (!slt) return null;
 if (slt.type.toLowerCase() == "select-multiple") {
  var len = Select.len(selectId);
  var result = [];
  for (var i = 0; i < len; i ++) {
   if (slt.options[i].selected) result.push(slt.options[i]);
  }
  return result.length > 1 ? result : (result.length == 0 ? null : result[0]);
 } else {
  var index = $(selectId).selectedIndex;
  return $(selectId).options[index];
 }
};
/**
 * 使指定索引位置的option被选中.从0开始.
 */
Select.select = function(/*string*/selectId, /*int*/index) {
 var slt = $(selectId);
 if (!slt) return false;
 for (var i = 0; i < slt.options.length; i ++) {
  if (index == i) {
   slt.options[i].setAttribute("selected", "selected");
   return true;
  }
 }
 return false;
};
/**
 * 选中指定的select的所有option选项,如果支持多选的话
 */
Select.selectAll = function(/*string*/selectId) {
 var len = Select.len(selectId);
 for (var i = 0; i < len; i ++) Select.select(selectId, i);
};
/**
 * 获取指定select的总的options个数
 */
Select.len = function(/*string*/selectId) {
 return $(selectId).options.length;
};
/**
 * 清除select中满足条件的options,如果没有指定处理方法则清除所有options项
 */
Select.clear = function(/*string*/selectId, /*function*/iterator) {
 if (typeof(iterator) != 'function') {
  $(selectId).length = 0;
 } else {
  var slt = $(selectId);
  for (var i = slt.options.length - 1; i >= 0; i --) {
   if (iterator(slt.options[i]) == true) slt.removeChild(slt.options[i]);
  }
 }
};
/**
 * 复制指定的select的option对象到另外一指定的select对象上.如果指定了处理
 * 函数,那么只有返回true时才会copy.
 * 函数iterator参数:当前处理的option对象、目标select的options数组
 */
Select.copy = function(/*string*/srcSlt, /*string*/targetSlt, /*function*/iterator) {
 var s = $(srcSlt), t = $(targetSlt);
 for (var i = 0; i < s.options.length; i ++) {
  if (typeof(iterator) == 'function') {
   if (iterator(s.options[i], $(targetSlt).options) == true) {
    t.appendChild(s.options[i].cloneNode(true));
   }
  } else {
   t.appendChild(s.options[i].cloneNode(true));
  }
 }
};

    那么在回调方法中就可以只要来调用:

……
var jsonString = xmlHttp.responeText; // 获取服务器返回的json字符串
var jsonObj = null;
try {
   jsonObj = eval('(' + jsonString + ')'); // 将json字符串转换成对象
} catch (ex) {
   return null;
}
Select.create("你的select的ID", jsonObj); // 执行option的添加
……

    在Select中提供了很多实用的JS方法来方便操作select对象,我们这里只使用其中的create方法。客户端有了JS,我们现在来做服务器端的字符串输出。这里我们用到了JSONLib库,该库可以很方便的来从现有的javaBean或其他集合对象中来转换成json字符串。我们这里也提供一个公用类如下:

package common.utils.json;

import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import net.sf.json.JSONArray;
import net.sf.json.JSONObject;

import org.apache.commons.beanutils.BeanUtils;
import org.apache.log4j.Logger;

/**
 * 下拉列表的JSON对象转换.
 * 转换后的字符串是如下格式:
 * {"options" : [ {"value" : 值,"text" : 文本}, 
 *       {"value" : 值,"text" : 文本},
 *       ……
 *       {"value" : 值,"text" : 文本}
 *              ]
 * }
 * 前台将利用两个JS进行转换和生成:
 * BaseClass对象的json方法将返回的字符串转换成对象;
 * Select对象的create/add方法将把转换后的对象添加到指定的select上去。
 * 
 * @author 铁木箱子
 *
 */
public class SelectJSON
{
 /**
  * Logger for this class
  */
 private static final Logger log = Logger.getLogger(SelectJSON.class);

 /**
  * 从指定的map对象中获取要设置的值后组装成返回给前台的JSON对象字符串.
  * 
  * 存储在map中的key-value应该是option中的value和text,即如下的option:
  * <option value="hello">你好</option>
  * 应该使用如下的map对象:
  * map.put("hello", "你好");
  * 注意使用map对象相同key值的将会被后设置的给覆盖!
  * 
  * @param map
  * @return
  */
 public static String fromMap(Map map)
 {
  Iterator it = map.keySet().iterator();
  JSONArray options = new JSONArray();
  while (it.hasNext()) {
   JSONObject option = new JSONObject();
   String key = (String)it.next();
   option.put("value", key);
   option.put("text", map.get(key));
   options.put(option);
  }
  JSONObject result = new JSONObject();
  result.put("options", options.toString());
  return result.toString();
 }
 
 /**
  * 从指定的list中获取要设置出去JSON对象.
  * 
  * 存放在list中的对象应该是满足JavaBean规范的POJO对象,同时还要指定该对象中的
  * 哪个属性作为option的value,哪个属性作为option的text。比如有如下一个JavaBean
  * ,其部分属性如下:
  * ……
  * public String getOptValue()
  * {
  *     return this.optValue;
  * }
  * public String getOptText()
  * {
  *     return this.optText;
  * }
  * ……
  * 如果我们想用optValue作为option的value属性,而optText作为option的text值,那么
  * 我们就应该传递参数分别是:optValue, optText.
  * 
  * @param list
  * @param valueProp
  * @param textProp
  * @return
  */
 public static String fromList(List list, String valueProp, String textProp)
 {
  JSONArray options = new JSONArray();
  try {
   for (Object obj : list) {
    JSONObject option = new JSONObject();
    String value = BeanUtils.getProperty(obj, valueProp);
    String text = BeanUtils.getProperty(obj, textProp);
    option.put("value", value);
    option.put("text", text);
    options.put(option);
   }
  } catch (Exception ex) {
   throw new RuntimeException(ex);
  }
  JSONObject result = new JSONObject();
  result.put("options", options.toString());
  return result.toString();
 }
 
 public static void main(String[] args)
 {
  // map 测试
  Map<String,String> tt = new HashMap<String,String>();
  tt.put("value1", "text1");
  tt.put("value2", "text2");
  tt.put("value3", "text3");
  log.info(SelectJSON.fromMap(tt));
 }
}

    在类SelectJSON中提供了两个方法,一个是从map中来获取并转换成json字符串,还一个就是从list中的对象来获取,这个方法需要使用BeanUtils工具来辅助获取JavaBean对象中的指定属性。当然了,你可以可以写其他方便发辅助方法来达到这样的效果。

    比如我们在上面的SelectJSON类中的测试,会输出:

{"options":[{"value":"value1","text":"text1"},{"value":"value2","text":"text2"},{"value":"value3","text":"text3"}]}

    然后我们再调用上面提到的JS类Select进行操作就可以了,注意,在使用Select类进行操作前,比如先转换服务器返回的字符串为js对象,即使用eval来执行返回字符串即可!好了,关于使用json来做动态下拉列表就说到这里咯,如有问题,欢迎一起交流~~~ 

分享到:
评论

相关推荐

    级联下拉菜单:级联表单下拉菜单

    级联下拉菜单jQuery插件,它允许您根据先前的选择来填充一组表单下拉菜单。演示版基本用法要使用该插件而不覆盖任何默认设置,您需要使用多个下拉(选择)菜单创建表单的结构。 在以下示例中,我正在使用&lt;form&gt...

    dynamicformgenerator:从JSON动态生成表单

    动态生成器从JSON动态生成表单

    简单方便的表单拖拽设计器(vue+ElementUI)

    - 2021-01-07: 增加json查看 - 2021-01-09: 增加icon选择组件,增加button选择按钮的支持 - 2021-01-12: 增加编辑器字数限制的校验、增加input输入框前后图标的配置 - 2021-01-18: 增加form-builder组件,增加渲染,...

    antd-schema-form:Based on Ant Design, interactive forms can be generated through JSON Schema configuration. - 基于Ant Design,可以通过JSON Schema配置生成可交互的表单

    此[Demo]( )仅显示了如何通过配置schema.json来构造表单。开始使用使用之前,需要在babel配置antd。 您需要按以下方式配置babel-loader: { test : / node_modules [ \\ / ] antd-schema-form [ \\ / ] . * \. ...

    item-generator:基于Antd3的配置化表单解决方案

    支持基础的表单类型配置,表单级联 支持注册自定义类型组件及挂钩组件,组件自定义模板 拉平数据类型处理(如:moment类型) 拉平不同表单配置(如:valueProp的处理) 解决不同表单元素类型展示UI出现错乱的问题...

    SpringMVC示例

    RequestParam 注解、RequestHeader 注解、CookieValue 注解、使用POJO作为参数(属性与页面自动匹配及级联)、使用Servlet原生API作为参数、处理模型数据(ModelAndView、Map、SessionAttributes 注解)、...

    SpringMVC Employee Demo

    view-controller标签转换成注解、自定义视图、重定向、Employee管理RESTRUL_CRUD_显示所有员工信息、RESTRUL_CRUD_添加操作&表单标签、RESTRUL_CRUD_删除操作&处理静态资源、RESTRUL_CRUD_修改操作、自定义类型转换...

    doctrine-entity-creator:一个简单的学说实体创建者和编辑者

    定义所有关联类型:一对一,一对多和多对多(包括自引用关系),选择拥有/相反的一面并配置级联操作 利用@IndexBy批注 定义索引和由它们索引的列 将存储库类分配给实体 对于实体字段,您可以定义该字段是否可为空,...

    超实用的jQuery代码段

    9.22 序列化表单到JSON数据 9.23 获取页面加载时间 9.24 将单个句子打断显示 9.25 限制只能输入中文、英文或数字 9.26 日期类型与时间戳的转换 9.27 使用数组模拟打字效果 9.28 获取数组中特定索引的最高值 9.29 ...

    Grails 中文参考手册

    5.3.3 级联更新和删除 5.3.4 立即加载和延迟加载 5.3.4 悲观锁和乐观锁 5.4 GORM查询 5.4.1 动态查找器 5.4.2 条件查询 5.4.3 Hibernate查询语言 5.5 高级GORM特性 5.5.1 事件和自动实现时间戳 5.5.2 自定义ORM映射 ...

    PHP+Ajax网站开发典型实例

    实例61 实现级联菜单的设计 实例62 PHP+Ajax树状菜单 第8章 Ajax数据库操作 实例63 显示数据库系统信息 实例64 实现数据库常见操作 实例65 完成数据库多种查询显示 实例66 数据库记录自动提示 实例67 AjaX...

    Ext 开发指南 学习资料

    4.4.7. 露一小手,组合上面所知,省市县三级级联。哈哈~ 4.4.7.1. 先做一个模拟的,所有数据都在本地 4.4.7.2. 再做一个有后台的,需要放在服务器上咯 4.5. 把form里的那些控件全部拿出来看看 4.6. form提交数据的...

    Java面试宝典2020修订版V1.0.1.doc

    1、用js和jQuery怎么进行表单验证 24 3、列举javaScript的3种主要数据类型,2种复合数据类型和2种特殊数据类型。 24 4、谈谈你的JS的理解? 24 5、ajax的优点? 25 6、简述一下ajax调试代码查找错误的方法? 26 7、...

    EXT教程EXT用大量的实例演示Ext实例

    4.4.7. 露一小手,组合上面所知,省市县三级级联。哈哈~ 4.4.7.1. 先做一个模拟的,所有数据都在本地 4.4.7.2. 再做一个有后台的,需要放在服务器上咯 4.5. 把form里的那些控件全部拿出来看看 4.6. form提交数据...

    EXT2.0中文教程

    4.4.7. 露一小手,组合上面所知,省市县三级级联。哈哈~ 4.4.7.1. 先做一个模拟的,所有数据都在本地 4.4.7.2. 再做一个有后台的,需要放在服务器上咯 4.5. 把form里的那些控件全部拿出来看看 4.6. form提交数据的...

    Java学习笔记-个人整理的

    \contentsline {chapter}{Contents}{2}{section*.1} {1}Java基础}{17}{chapter.1} {1.1}基本语法}{17}{section.1.1} {1.2}数字表达方式}{17}{section.1.2} {1.3}补码}{19}{section.1.3} {1.3.1}总结}{23}{...

    低清版 大型门户网站是这样炼成的.pdf

    3.7.4 基于json插件的ajax实现 185 3.8 小结 190 第4章 orm中间件名流hibernate 3接管持久层 191 4.1 orm简介 191 4.1.1 持久化与持久层 191 4.1.2 jdbc劣势 192 4.1.3 实体域模型与关系数据模型 193 4.1.4 ...

    Spring.3.x企业应用开发实战(完整版).part2

    15.6.2 编写控制器和文件上传表单页面 15.7 杂项 15.7.1 静态资源处理 15.7.2 装配拦截器 15.7.3 异常处理 15.8 小结 第5篇 测试及实战 第16章 实战型单元测试 16.1 单元测试概述 16.1.1 为什么需要单元测试 16.1.2...

    Spring3.x企业应用开发实战(完整版) part1

    15.6.2 编写控制器和文件上传表单页面 15.7 杂项 15.7.1 静态资源处理 15.7.2 装配拦截器 15.7.3 异常处理 15.8 小结 第5篇 测试及实战 第16章 实战型单元测试 16.1 单元测试概述 16.1.1 为什么需要单元测试 16.1.2...

    python入门到高级全栈工程师培训 第3期 附课件代码

    02 级联删除与set null 03 多表查询之连接查询 04 多表查询之复合查询与子查询 05 mysql之索引 第48章 01 python操作数据库pymysql 02 数据库之事务 03 mysql事务之savepoint 第49章 01 http协议之请求协议 02 ...

Global site tag (gtag.js) - Google Analytics