Angular ui-select报错:无法在字符串上创建'id'属性求助
这个问题我之前在使用ui-select的多选标签功能时也踩过坑,核心原因很明确:tagging模式默认会把你输入的新增内容以字符串形式加入数组,但你的代码(或者ui-select内部的sortable逻辑)期望处理的是带id/uuid属性的对象,当它试图给字符串类型的条目添加id属性时,就会抛出这个错误。
问题根源拆解
你当前的模板里,model[qualifier]应该是一个字符串数组,而tagging功能默认新增的也是字符串。但select.js里的代码$select.selected[j].id = $select.selected[j].uuid试图给这个字符串添加属性,这在JS里是不允许的——字符串是原始类型,不能直接添加自定义属性。
解决方案:把新增标签转换成对象
我们需要修改tagging的行为,让新增的条目变成对象,而不是字符串,同时调整模板的显示和遍历逻辑:
1. 控制器中添加tagging回调函数
在你的Angular控制器里,定义一个用来创建新条目的函数,返回带唯一标识(比如id)和文本属性的对象:
$scope.createNewItem = function(tag) { // 这里可以用uuid生成器或者自增id,示例用时间戳+随机数生成唯一id return { id: Date.now() + Math.random(), name: tag // 用输入的tag作为显示的文本内容 }; };
2. 修改ui-select模板
调整模板的tagging属性指向我们的回调,同时修改repeat、显示逻辑,适配对象数组:
<ui-select multiple tagging="createNewItem($tag)" <!-- 新增:用回调生成对象类型的新标签 --> tagging-label="添加新标签" <!-- 可选:设置新增按钮的提示文本 --> data-ng-disabled="!field.editable" data-ng-model="model[qualifier]" theme="select2" title="" sortable="true" style="width: 100%;"> <!-- 匹配项显示对象的name属性 --> <ui-select-match placeholder="{{field.tooltip| translate}}" name="{{field.qualifier}}"> <span id="myfield-{{field.qualifier}}">{{$item.name}}</span> </ui-select-match> <!-- 遍历对象数组,用track by option.id避免重复渲染问题 --> <ui-select-choices id="{{field.qualifier}}-myfield" repeat="option in model[qualifier]| filter: $select.search track by option.id"> <small> <span>{{option.name}}</span> <!-- 显示对象的name属性 --> </small> </ui-select-choices> </ui-select>
3. 统一初始数据格式
如果你的model[qualifier]原本是字符串数组,需要把它转换成对象数组,保证数据格式统一:
// 假设原来的数组是["xxx", "yyy"],转换成对象数组 $scope.model[qualifier] = $scope.model[qualifier].map(item => ({ id: Date.now() + Math.random(), name: item }));
为什么这样能解决问题?
修改后,无论是已有的条目还是新增的标签,都是带id属性的对象,select.js里的代码$select.selected[j].id = ...就可以正常给对象添加/修改属性,不会再出现“给字符串创建属性”的错误,同时也能更好地支持sortable这类需要唯一标识的功能。
内容的提问来源于stack exchange,提问作者Apoorv Srivastav

