情况:
我正在制作一个有角度的应用程序,我必须使用ui选择:在用户信息页面中,在选择中必须可以选择一个或多个标签。它几乎可以工作了,除了我在获取和显示预先存在的标签方面遇到了问题。
代码:
视图:
<ui-select multiple ng-model="info_data.tags" theme="bootstrap" ng-disabled="disabled">
<ui-select-match placeholder="Select tag...">{{$item.name}} </ui-select-match>
<ui-select-choices repeat="tag in all_tags | propsFilter: {name: $select.search}">
{{tag.name}}
</ui-select-choices>
</ui-select>
<p>Selected: {{info_data.tags}}</p>
控制器:
$http({
url: base_url + 'main/db_get_all_tags',
method: "POST",
}).success(function (data) {
$scope.all_tags = data;
});
$scope.show_info = function() {
var result_info = DbService.get_info( $stateParams.db_data_id );
result_info.then( function( data )
{
$scope.info_data = data;
});
};
尝试1:
这是一种非常奇怪的行为。我在用户的信息页面上看不到标签,甚至在ui select中也看不到。除非刷新5/6次,否则它会突然神奇地工作,在用户信息页面和用户界面选择中显示标签。在这两种情况下,无论是否工作,我都会收到几种相同类型的错误消息:
无法读取未定义的属性"length"。
尝试2:
为了解决这个问题,我在控制器中添加了以下代码:
$scope.info_data = { tags: [] };
$scope. all_tags = [];
我再也没有收到任何错误消息。这个应用程序很稳定,我可以在用户信息页面上看到正确的标签。唯一的问题是标签不再加载到ui select中。
如果我选择了一个新的标签,那么它工作得很好,但我丢失了预先存在的标签。
问题:
如何使ui选择正确工作?(当前版本0.8.3)有冲突的问题吗?
如何从服务器正确调用预先存在的数据?
非常感谢!
您没有特别描述您看到的错误,所以我不知道以下内容是否会有所帮助。。
我最初在使用ui select演示代码作为示例时遇到了一个问题,因为他们使用的是propsFilter过滤器,这是他们为演示编写的自定义过滤器:
<ui-select-choices repeat="tag in all_tags | propsFilter: {name: $select.search}">
我假设您没有在代码中包含此筛选器,这可能是您遇到问题的原因。您可以使用angular的法线过滤器:来解决它
<ui-select-choices repeat="tag in all_tags | filter: {name: $select.search}">
或者,如果您有多个属性要筛选,则可以编写propsFilter筛选器以在OR而不是AND上进行筛选。如果使用"filter"筛选多个属性,它将尝试在所有属性中匹配搜索值。
app.filter('propsFilter', function() {
return function(items, props) {
var out = [];
if (angular.isArray(items)) {
items.forEach(function(item) {
var itemMatches = false;
var keys = Object.keys(props);
for (var i = 0; i < keys.length; i++) {
var prop = keys[i];
var text = props[prop].toLowerCase();
if (item[prop].toString().toLowerCase().indexOf(text) !== -1) {
itemMatches = true;
break;
}
}
if (itemMatches) {
out.push(item);
}
});
} else {
// Let the output be the input untouched
out = items;
}
return out;
};
});
你可以在这里看到带有过滤器的提交:https://github.com/angular-ui/ui-select/commit/3fac88cfad0ad2369c567142eadba52bdb7998b1
尽管如果您有一些特定的过滤要求,我建议您编写自己的过滤器,以确保最佳性能。
我不知道Select2#4.0之前的情况是什么样的,但如果没有angular-ui-select
(而且它减少了一个依赖项),使用它真的没那么难
只需将select2
包含在bower依赖项中,并在指令中的link
函数中使用:
.directive('someDirective', function() {
return {
restrict: 'E',
link: function(scope, element, attrs) {
element.find('.your-select2').select2({
theme: 'classic',
placeholder: 'Select a placeholder...',
allowClear: true,
data: [{ id: 'New', text: 'New'}]...
});
},
};
})
和您的HTML:
<select class="your-select2" ng-model="a.model.field"></select>
如果需要,您也可以通过服务从控制器加载data
,然后只需使用scope
即可进行设置!
当我尝试使用angular-ui-select
时,我这么说是因为我想"嘿,这是Angular,你必须为它使用插件!",但事实并非总是如此:)。另外,我发现文档没有那么有用(称我懒惰,但嘿)
我对propsFilter进行了一些优化。它正在进行
props[prop].toLowerCase();
在items迭代中,但实际上只需要评估我们拥有的属性的多少倍。目前评估为items count * props count
。
因此,最终优化的代码如下所示:
app.filter('casinoPropsFilter', function() {
return function(items, props) {
var out = [];
if (angular.isArray(items)) {
var keys = Object.keys(props);
var propCache = {};
for (var i = 0; i < keys.length; i++) {
var prop = keys[i];
var text = props[prop].toLowerCase();
propCache[props[prop]] = text;
}
items.forEach(function(item) {
var itemMatches = false;
for (var i = 0; i < keys.length; i++) {
var prop = keys[i];
var text = propCache[props[prop]];
if (item[prop].toString().toLowerCase().indexOf(text) !== -1) {
itemMatches = true;
break;
}
}
if (itemMatches) {
out.push(item);
}
});
} else {
// Let the output be the input untouched
out = items;
}
return out;
};
});