You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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_

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.20 12:21:53