本文介绍了动态修改控件元数据的需求背景、思路与方案分析、实现过程、实现效果、开发环境、注意事项及参考资料。通过插件在运行时重写元数据,实现动态修改控件的背景色、前景色、编辑风格等。实现过程中详细说明了如何编写插件代码、获取属性标识、拼接数据结构,并给出了修改单据体、卡片分录、单据列表及报表列元数据的示例。最后提醒了注意事项并提供了参考资料链接。
关键字:动态修改元数据
一、需求背景
比如我们需要动态修改控件的背景色,前景色,动态设置控件的样式等。
我们举两个例子。
1、修改文本控件的编辑风格,这里有三种风格:文本框编辑,按钮点击编辑,按钮+文本编辑
2、修改按钮的前景色、背景色
二、思路与方案
分析:类似的这些属性是以元数据(xml)的格式存储于数据库,第一次保存的时候会创建对应单据的元数据,之后有修改元数据会更新元数据,插件可以在运行期重写指定的元数据,从而做到动态修改元数据。
三、实现过程
1.插件代码:
import kd.bos.form.ClientProperties; import kd.bos.form.plugin.AbstractFormPlugin; import java.util.EventObject; import java.util.HashMap; public class TextFieldDemo extends AbstractFormPlugin { /** * 插件修改元数据 * @param e */ @Override public void beforeBindData(EventObject e) { super.beforeBindData(e); //修改文本字段元数据 HashMap<String, Object> fieldMap = new HashMap<>(); //设置文本控件的编辑类型,这里修改为按钮+文本编辑 HashMap<String, Object> itemMap = new HashMap<>(); //设置文本是否可编辑的属性 itemMap.put(ClientProperties.Editable, true); //设置文本是否展示点击按钮的属性 itemMap.put(ClientProperties.ShowEditButton, true); //把属性map添加到控件的map中,在元数据中查看过后key为item fieldMap.put("item", itemMap); //同步指定元数据到文本控件 this.getView().updateControlMetadata("kdec_textfield", fieldMap); // 修改按钮控件元数据 fieldMap = new HashMap<>(); //设置背景色 fieldMap.put(ClientProperties.BackColor, "green"); //设置前景色 fieldMap.put(ClientProperties.ForeColor, "red"); //同步指定元数据到按钮控件 this.getView().updateControlMetadata("kdec_buttonap", fieldMap); } }
2.获取标识:
那么问题来了,我们该怎么获取需要修改的属性的标识,怎么拼接数据结构???
我们可以在设计器中修改对应的属性,然后保存页面,然后打开f12,点击预览(必须要修改对应的控件的属性,才会看到)我们会看到一个/getMetadata.do?fid=XXXX&version=XXXX的请求,这就是获取元数据的接口,每次修改元数据之后,点击预览会重新加载元数据。我们需要来查看接口响应的数据结构来确定修改的相关属性及结构!!!如果结构不一致是修改不成功的!!!接下来以文本的编辑风格为例:
我们分别修改文本的编辑风格为三种不同的值,并保存预览,查看接口的响应值如图:
文本编辑框的响应如图:
按钮点击编辑的响应如图:
按钮+文本编辑的响应如图
接下来我们对这三个响应结果进行“找不同”,就会发现,这里有两个值不同,分别是:eb和showEditButton,我们合理的猜想一下,eb为editable,即可编辑;showEditButton即为展示点击按钮,并且我们能发现这些属性是在文本控件的item集合里,这是个map集合,所以组装数据的时候需要在文本属性的map中放置名为item的map。最后我们可以通过插件验证下我们的猜想,经过验证最终证明方法合理。其他属性同理。
注意:这里有个细节点,我们插件里面设置值的时候要严格和返回的元数据格式保持一致,举个板栗:
我们上面的文本控件的编辑风格由两个值控制,eb和showEditButton,所以大家很容易去理解成:只可点击就把eb设为false,showEditButton设为ture,只可编辑就把eb设置为true,showEditButton设为false,但是这个理所当然的想法是错误的!!!我们必须严格按照最终展示的元数据的格式去构造元数据。比如我们要设置为只可编辑,看元数据返回没有这两个值,那我们插件中就不能给这两个值,设置为false也不行;要设置为只点击,就按元数据格式把eb设为false,showEditButton设为true。
再讲下我们怎么定位到需要验证的控件的属性。我们返回的数据结构如下图
大家细心一点会发现,每一层级这个id的值都对应我们页面上的容器标识,第一级为单据的标识,下来就是页面里面的容器标识,容器有flex面板、字段布局面板、页签等等。大家寻找所需控件的时候按照界面上的层级关系去查看数据就好。
我们更新元数据的方法为:
this.getView().updateControlMetadata("key", fieldMap);
这里我们以单个控件的元数据为单位,所以后面的map结构只需以单个控件的元数据结构进行构造即可,即不需要到外层容器的层级,只需构造最里面的控件节点的数据。
四、实现效果
如图所示:
设计器设置文本控件的编辑风格为文本框编辑。
按钮前景色、背景色也为默认值
经过插件干预之后,页面显示是这样的:
五、开发环境版本
不限
六、注意事项
注意:我们修改元数据只能修改单个控件的元数据,对于单据体这种动态渲染出来的,我们修改列的元数据就是修改了整列的数据而不是单行或者单个单元格,对于单据体我们插件有封装修改单行或者单个单元格背景色等样式的方法:
EntryGrid entryGrid = this.getControl("treeentryentity"); //设置单据体指定行的背景色 entryGrid.setRowBackcolor("yellow", new int[]{0}); //设置单据体指定单元格的背景色 ArrayList<CellStyle> cellStyles = new ArrayList<>(); CellStyle cellStyle = new CellStyle(); cellStyle.setFieldKey("textfield1"); cellStyle.setRow(0); cellStyle.setBackColor("blue"); cellStyles.add(cellStyle); entryGrid.setCellStyle(cellStyles);
1.对于卡片分录和单据列表,我们可以通过界面规则去设置背景色等。
2.单据列表相关前景色背景色修改或者其他相关操作可以查看另外一个帖子:https://club.kdcloud.com/article/183450
3.对于报表的列元数据,可以在报表取数插件的getColumns()方法中修改列元数据。(按照上文表单插件的方式不生效)
七、参考资料
如果发现文章有什么问题欢迎大家指出,我将积极验证修改。如果有帮到你,还请来一波三连:关注,点赞,收藏。觉得有用也可以分享到公司群,惠及其他同事,感谢您的耐心观看~~~
动态修改元数据案例.zip(8.88KB)
推荐阅读