SAPUI5绑定JSON Model的Multi Input删除token后重复出现问题求助
嗨,这个问题我之前做SAPUI5项目时也踩过坑!核心问题很明确:你只处理了添加Token时的模型同步,但完全没管删除操作——界面上点叉删了Token,可JSON Model里的对应数据还好好待着,等你加新Token时,模型里旧的数据又会被重新渲染出来,就出现了你说的情况。
下面给你两种解决思路,优先推荐第一种,因为更符合SAPUI5的绑定设计理念,能减少手动维护的麻烦:
方案一:用双向绑定实现自动同步(推荐)
SAPUI5的MultiInput控件支持直接把tokens属性双向绑定到JSON Model的数组,这样不管是添加还是删除Token,控件都会自动同步模型数据,不需要你手动处理界面和模型的同步逻辑。
步骤1:准备模型结构
确保你的JSON Model里有一个用于存储Token数据的数组,比如:
// 初始化模型 const oMyModel = new sap.ui.model.json.JSONModel({ selectedItems: [] // 这个数组用来存所有Token对应的数据 }); this.getView().setModel(oMyModel, "myModel"); // 可以设置命名模型,避免和默认模型冲突
步骤2:视图里绑定MultiInput
在XML视图(或JS视图)里,把MultiInput的tokens属性双向绑定到模型数组,同时配置Tokenizer的key和text对应模型字段:
<MultiInput id="myMultiInput" placeholder="输入或选择条目" tokens="{path: 'myModel>/selectedItems', mode: 'TwoWay'}" suggest="onSuggest"> <!-- 如果你用了建议功能的话 --> <tokenizer> <Tokenizer key="{myModel>id}" <!-- 对应模型里的唯一标识,用来区分不同条目 --> text="{myModel>name}" /> <!-- 对应Token显示的文本 --> </tokenizer> </MultiInput>
步骤3:修改添加Token的逻辑
原来你在addValidator里手动调用addToken的逻辑,改成直接往模型数组里push数据就行,控件会自动渲染出对应的Token:
multiInputField.addValidator(function(args) { const oSuggestion = args.suggestionObject; // 假设这是你的建议对象 const oModel = this.getView().getModel("myModel"); const aSelectedItems = oModel.getProperty("/selectedItems"); // 先判断是否已经存在,避免重复添加 const bExists = aSelectedItems.some(item => item.id === oSuggestion.getId()); if (!bExists) { aSelectedItems.push({ id: oSuggestion.getId(), name: oSuggestion.getName() }); oModel.setProperty("/selectedItems", aSelectedItems); // 更新模型,控件自动同步界面 } return true; // 验证通过返回true }.bind(this)); // 注意绑定this指向控制器
这样设置后,当你点击Token旁的叉删除时,双向绑定会自动把模型数组里的对应条目删掉,完全不需要额外处理删除逻辑!
方案二:手动监听删除事件同步模型
如果因为项目现有架构限制,没法用双向绑定,那你就需要手动监听MultiInput的tokenDelete事件,在事件触发时同步删除模型里的对应数据。
步骤1:视图里绑定删除事件
给MultiInput添加tokenDelete事件绑定:
<MultiInput id="myMultiInput" placeholder="输入或选择条目" tokenDelete="onTokenDelete" ...> <!-- 其他原有配置 --> <tokenizer> <Tokenizer key="{id}" <!-- 一定要设置key,用来匹配模型里的条目 --> text="{name}" /> </tokenizer> </MultiInput>
步骤2:控制器里实现删除逻辑
在控制器里写onTokenDelete方法,找到模型里对应删除的Token数据并移除:
onTokenDelete: function(oEvent) { const oDeletedToken = oEvent.getParameter("token"); const sTokenKey = oDeletedToken.getKey(); // 获取删除Token的key const oModel = this.getView().getModel(); // 或者你的命名模型 const aSelectedItems = oModel.getProperty("/selectedItems"); // 找到模型里对应key的条目索引 const iDeleteIndex = aSelectedItems.findIndex(item => item.id === sTokenKey); if (iDeleteIndex !== -1) { aSelectedItems.splice(iDeleteIndex, 1); // 删除数组里的对应条目 oModel.setProperty("/selectedItems", aSelectedItems); // 更新模型 } }
这样每次删除界面上的Token时,都会同步删掉模型里的对应数据,就不会出现旧数据又冒出来的问题了。
注意事项
- 不管用哪种方案,都要确保Token的
key和模型里的唯一标识对应上,不然删除时找不到要删的条目。 - 尽量避免手动调用
addToken/removeToken这类方法,尤其是用了双向绑定之后,手动操作界面会和模型同步逻辑冲突,反而容易出问题。
内容的提问来源于stack exchange,提问作者jaku_

