动态添加基础资料控件原创
金蝶云社区-技术支持与赋能部_ZH
技术支持与赋能部_ZH
16人赞赏了该文章 3,945次浏览 未经作者许可,禁止转载编辑于2022年06月21日 10:43:07
summary-icon摘要由AI智能服务提供

本文讨论了如何根据项目需求动态生成基础资料控件,以满足特殊业务场景。通过插件方式直接生成控件,更灵活且不浪费资源。具体实现包括重写几个关键方法,如`loadCustomControlMetas`动态添加控件配置,`beforeBindData`注册动态字段到数据绑定器,`onGetControl`创建控件实例并处理事件,`getEntityType`修改实体模型增加属性等。还提供了创建动态面板和向实体注册属性的封装方法。最终实现了在单据中动态添加基础资料控件的功能。

关键词:动态,基础资料控件

一、需求

有些项目的单据需要根据条件展示不同的控件(尤其基础资料)以满足特殊的业务场景

二、思路与方案

2.1分析思路

实现这个功能有两种方式,一种是通过控件的显示隐藏,另一种方式是通过插件直接生成。前者明显是提前预置好的,给人的感觉是动态生成的,但其实本质不是动态的,需要提前知道有那些控件有多少控件要预置,不够灵活。而后者通过插件直接动态生成,优势是做到了真正的动态生成控件,不浪费存储资源和界面资源,十分灵活。本文讲述的是第二种方案

2.2实现方案

说到动态添加控件,就需要重写loadCustomControlMetas,beforeBindData,onGetControl,getEntityType方法,调整后台数据模型及数据包。这是必须要实现的

 三、实现过程

1:表单注册插件,该插件继承AbstractFormPlugin


2、loadCustomControlMetas:向前端动态添加控件配置

/**
	 * 界面显示前,触发此事件:向前端界面输出动态添加的字段、控件
	 * @remark
	 * 这个事件只能向前端界面添加字段、控件;后台的视图模型、数据模型,均没有改变
	 */
	@Override
	public void loadCustomControlMetas(LoadCustomControlMetasArgs e) {
		// TODO Auto-generated method stub
		super.loadCustomControlMetas(e);
		//建一个面板,并向其中动态添加字段、控件
		FlexPanelAp headAp = this.createDynamicPanel();
		Map<String, Object> mapHead = new HashMap<>();
		mapHead.put(ClientProperties.Id, "kded_advconchildpanelap");
		mapHead.put(ClientProperties.Items, headAp.createControl().get(ClientProperties.Items));
		e.getItems().add(mapHead);
	}


3、beforeBindData:向界面编程模型,动态添加字段编程模型(FieldEdit)

/**
	 * 此事件在把数据绑定到界面之前触发:
	 * 系统会调用FormDataBinder对象,把字段值输出给前端字段编辑控件;
	 * @param e
	 * @remark
	 * 动态添加的字段,在FormDataBinder中并没有记录,因此,默认不会绑定动态添加的字段值;
	 * 必须在此事件,向FormDataBinder中注册动态添加的字段
	 */
	@Override
	public void beforeBindData(EventObject e) {
		// TODO Auto-generated method stub
		super.beforeBindData(e);
		// 单据头添加的字段、控件,注入到容器面板的控件编程模型中
		FlexPanelAp dynamicPanel = this.createDynamicPanel();
		Container myFldPanel = this.getView().getControl("kded_advconchildpanelap");
		myFldPanel.getItems().addAll(dynamicPanel.buildRuntimeControl().getItems());
		this.getView().createControlIndex(myFldPanel.getItems());
	}

4、onGetControl:创建动态控件的实例,并捕获控件事件

	/**
	 * 用户与自定义的控件进行交互时,会触发此事件
	 * @remark
	 * 插件在此事件中,创建自定义控件的编程模型,并侦听其事件
	 */
	@Override
	public void onGetControl(OnGetControlArgs e) {
		// TODO Auto-generated method stub
		super.onGetControl(e);
		if(e.getKey().equals("testbase")) {
			// 用户点击控件时,会触发此事件:创建基础资料的控件编程模型BasedataEdit实例返回
			BasedataEdit baseEdit= new BasedataEdit();
			baseEdit.setKey("testbase");
			baseEdit.setView(this.getView());
			e.setControl(baseEdit);
		}
	}


5、getEntityType:修改实体模型,增加属性

/**
	 * 此事件在系统要用到表单主实体模型时触发
	 * @param e
	 * @remark
	 * 插件修改原始主实体,注册自定义属性,返回新的主实体给系统
	 */
	@Override
	public void getEntityType(GetEntityTypeEventArgs e) {
		// 取原始的主实体
		MainEntityType oldMainType = e.getOriginalEntityType();
		// 复制主实体
		MainEntityType newMainType = null;
		try{
			newMainType = (MainEntityType)oldMainType.clone();
		}
		catch (CloneNotSupportedException exp){
			throw new KDException(exp, new ErrorCode("LoadCustomControlMetasSample", exp.getMessage()));
		}
		// 为自定义的文本字段,向主实体注册属性
		this.registDynamicProps(newMainType);
		
		// 回传主实体给系统
		e.setNewEntityType(newMainType);
	}


6、自定义封装的方法(动态添加控件,向实体注册属性)

/**
	 * 创建一个面板,并向其中动态添加字段、控件
	 */
	private FlexPanelAp createDynamicPanel(){
		
		FlexPanelAp headPanelAp = new FlexPanelAp();
		headPanelAp.setKey("headAp");

		FieldAp fieldAp = new FieldAp();
		fieldAp.setId("testbase");
		fieldAp.setKey("testbase");
		fieldAp.setName(new LocaleString("动态基础资料"));
		fieldAp.setFireUpdEvt(true);	// 即时触发值更新事件
		
		BasedataField ba=new BasedataField();
		ba.setId("testbase");
		ba.setKey("testbase");
		ba.setBaseEntityId("bd_currency");
		fieldAp.setField(ba);
		headPanelAp.getItems().add(fieldAp);
		return headPanelAp;
	}
	/**
	 * 向主实体注册动态添加的属性
	 */
	private void registDynamicProps(MainEntityType newMainType){
		// 向单据头动态注册一个新的基础资料属性
		BasedataProp bdpackPrp = new BasedataProp();
        bdpackPrp.setDbIgnore(true);
       // bdpackPrp.setBaseEntityId("bd_material");
        bdpackPrp.setName("testbase");
        bdpackPrp.setDisplayName(new LocaleString("动态基础资料添加"));
        bdpackPrp.setAlias("");
        bdpackPrp.setBaseEntityId("bd_currency");
        EntityType dataEntityType = EntityMetadataCache.getDataEntityType("bd_currency");
        bdpackPrp.setComplexType(dataEntityType);
		// 把新字段,注册到单据头
        newMainType.addProperty(bdpackPrp);
		newMainType.registerComplexProperty(bdpackPrp);
	}


四 实现效果:

原单:并没有基础资料控件

20220621103313725.png


动态添加后:

20220621103500067.png

 五、开发环境版本

v4.0.018.0

六、注意事项

1、实现步骤比较多,可以仔细看一下每一步的作用,如果少了一步就会导致功能无法生效

七、参考资料

文档中心

学习成长中心


Dtbase.rar(1.98KB)

图标赞 16
16人点赞
还没有人点赞,快来当第一个点赞的人吧!
图标打赏
0人打赏
还没有人打赏,快来当第一个打赏的人吧!