允许在 ui-select 中手动输入文本
Allow manually entered text in ui-select
我正在使用来自 ui-select 的 select 盒子。一切正常,但我想允许手动输入文本,并且不想限制用户使用列表中的可用值。如果我输入文本,它会正确过滤我的列表。但是,当我不单击某个元素并转到下一个字段时,我的文本将被丢弃。
有什么想法吗?
感谢和问候,
亚历克斯
我不想显示我的代码,因为我认为它不正确,但有人要求:
<ui-select ng-model="formData[field.id].selected" theme="bootstrap">
<ui-select-match placeholder="{{ lists[field.id].placeholder }}">{{$select.selected.text}}</ui-select-match>
<ui-select-choices repeat="item in lists[field.id].list | filter: $select.search">
<div ng-bind-html="item.text | highlight: $select.search"></div>
</ui-select-choices>
</ui-select>
数据存储在formData[field.id].selected
中。 field.id
是要显示的当前字段的编号(我正在动态生成我的表单)。假设它存储一个唯一的 int 值。
编辑 08.04.2015
我的解决方案:
我发现似乎没有 equivalent 到 C# 组合框。所以我继续使用两个单独的字段。这不是我想要的,但现在可以使用:
<ui-select ng-model="formData[field.id].selected" theme="bootstrap">
<ui-select-match placeholder="{{ lists[field.id].placeholder }}">{{$select.selected.text}}</ui-select-match>
<ui-select-choices repeat="item in lists[field.id].list | filter: $select.search">
<div ng-bind-html="item.text | highlight: $select.search"></div>
</ui-select-choices>
</ui-select>
<?php echo __('Create a new element if value is not in list'); ?>
<div class="input-group">
<span class="input-group-addon">
<input type="checkbox" ng-model="disabled[field.id]">
</span>
<input type="text" value="" ng-disabled="!disabled[field.id]" class="form-control" ng-model="formData[field.id].newValue" />
</div>
您可以使用 tagging 属性,如文档中所述:
https://github.com/angular-ui/ui-select/wiki/ui-select
<ui-select multiple tagging tagging-label="(custom 'new' label)" ng-model="multipleDemo.colors">
...
</ui-select>
我想我找到了一种允许用户创建新条目的方法。使用 "on-select" 属性传递一个以 $select 作为参数的函数,如下所示:
<ui-select ng-model="person.selected"
theme="select2"
on-select="peopleSel($select)"
tagging
reset-search-input="false"
>
<ui-select-match placeholder="Enter a name...">{{$select.selected.name}}</ui-select-match>
<ui-select-choices repeat="sel in people | filter: {name: $select.search}">
<div ng-bind-html="sel.name | highlight: $select.search"></div>
</ui-select-choices>
</ui-select>
然后创建当 clickTriggeredSelect 变量为 false 时添加新条目的函数:
$scope.peopleSel= function(sel) {
if ( sel.search && ! sel.clickTriggeredSelect ) {
if ( ! sel.selected || sel.selected.name != sel.search ) {
//Search for an existing entry for the given name
var newOne= personSearch( sel.search );
if ( newOne === null ) {
//Create a new entry since one does not exist
newOne= { name: sel.search, email: 'none', country: 'unknown' };
$scope.people.push( newOne );
}
//Make the found or created entry the selected one
sel.selected= newOne;
}
}
sel.search= ''; //optional clearing of search pattern
};
请注意,此处未提供 personSearch 定义。此外,这种测试 clickTriggeredSelect 的方法可用于允许用户取消 select 如果空白条目是首选项的字段。
PVC
这里有一个解决方案:
HTML -
<ui-select ng-model="superhero.selected">
<ui-select-match placeholder="Select or search a superhero ...">{{$select.selected}}</ui-select-match>
<ui-select-choices repeat="hero in getSuperheroes($select.search) | filter: $select.search">
<div ng-bind="hero"></div>
</ui-select-choices>
</ui-select>
控制器 -
$scope.getSuperheroes = function(search) {
var newSupes = $scope.superheroes.slice();
if (search && newSupes.indexOf(search) === -1) {
newSupes.unshift(search);
}
return newSupes;
}
这里是 CodePen solution.
我已经分叉了 ui-select 项目以通过 allow-free-text 属性允许此功能
<ui-select allow-free-text="true" ng-model="ctrl.freeTextDemo.color2" theme="bootstrap" style="width: 800px;" title="Choose a color">
<ui-select-match placeholder="Select color...">{{$select.selected}}</ui-select-match>
<ui-select-choices repeat="color in ctrl.availableColors | filter: $select.search">
<div ng-bind-html="color | highlight: $select.search"></div>
</ui-select-choices>
</ui-select>
这是plnker
在 angular-ui 团队接受我的 pull request 之前,您可以获得 ui-select build,其中包括我在 my own repo
上的补丁
我用keyup
添加了一个新的选项代表输入的文字。使用这种方法,如果用户按 enter
,他们可以 select 目前输入的内容(默认活动项目是第一个项目)。
当数据列表包含纯文本或对象(需要属性value-prop
)时,这两种情况都支持。
指令:
commonApp.directive("uiSelectFreeText", function () {
return {
restrict: "A",
require: "uiSelect",
link: function (scope, element, attrs, $select) {
var searchInput = element.querySelectorAll("input.ui-select-search");
if (searchInput.length !== 1) {
console.log("Error! Input not found.");
return;
}
searchInput.on("keyup", function () {
var valueProp = attrs["valueProp"];
var addNewObjOption = function () {
// add new item represent free text option
var newOption = { isFreeText: true };
newOption[valueProp] = $select.search;
$select.items.unshift(newOption);
};
if ($select.items.length > 0) {
var firstItem = $select.items[0];
if (valueProp) {
// items is list of Object
if (firstItem.isFreeText) {
firstItem[valueProp] = $select.search;
} else {
addNewObjOption();
}
} else {
// items is list of string
if (firstItem === $select.search) {
return;
} else {
$select.items.push($select.search);
}
}
} else {
if (valueProp) {
addNewObjOption();
} else {
// items is list of string
$select.items.push($select.search);
}
}
});
}
};
});
HTML:
<ui-select class="ui-select-control"
ui-select-free-text value-prop="Label"
ng-model="keyword">
</ui-select>
我正在使用来自 ui-select 的 select 盒子。一切正常,但我想允许手动输入文本,并且不想限制用户使用列表中的可用值。如果我输入文本,它会正确过滤我的列表。但是,当我不单击某个元素并转到下一个字段时,我的文本将被丢弃。
有什么想法吗?
感谢和问候, 亚历克斯
我不想显示我的代码,因为我认为它不正确,但有人要求:
<ui-select ng-model="formData[field.id].selected" theme="bootstrap">
<ui-select-match placeholder="{{ lists[field.id].placeholder }}">{{$select.selected.text}}</ui-select-match>
<ui-select-choices repeat="item in lists[field.id].list | filter: $select.search">
<div ng-bind-html="item.text | highlight: $select.search"></div>
</ui-select-choices>
</ui-select>
数据存储在formData[field.id].selected
中。 field.id
是要显示的当前字段的编号(我正在动态生成我的表单)。假设它存储一个唯一的 int 值。
编辑 08.04.2015 我的解决方案: 我发现似乎没有 equivalent 到 C# 组合框。所以我继续使用两个单独的字段。这不是我想要的,但现在可以使用:
<ui-select ng-model="formData[field.id].selected" theme="bootstrap">
<ui-select-match placeholder="{{ lists[field.id].placeholder }}">{{$select.selected.text}}</ui-select-match>
<ui-select-choices repeat="item in lists[field.id].list | filter: $select.search">
<div ng-bind-html="item.text | highlight: $select.search"></div>
</ui-select-choices>
</ui-select>
<?php echo __('Create a new element if value is not in list'); ?>
<div class="input-group">
<span class="input-group-addon">
<input type="checkbox" ng-model="disabled[field.id]">
</span>
<input type="text" value="" ng-disabled="!disabled[field.id]" class="form-control" ng-model="formData[field.id].newValue" />
</div>
您可以使用 tagging 属性,如文档中所述: https://github.com/angular-ui/ui-select/wiki/ui-select
<ui-select multiple tagging tagging-label="(custom 'new' label)" ng-model="multipleDemo.colors">
...
</ui-select>
我想我找到了一种允许用户创建新条目的方法。使用 "on-select" 属性传递一个以 $select 作为参数的函数,如下所示:
<ui-select ng-model="person.selected"
theme="select2"
on-select="peopleSel($select)"
tagging
reset-search-input="false"
>
<ui-select-match placeholder="Enter a name...">{{$select.selected.name}}</ui-select-match>
<ui-select-choices repeat="sel in people | filter: {name: $select.search}">
<div ng-bind-html="sel.name | highlight: $select.search"></div>
</ui-select-choices>
</ui-select>
然后创建当 clickTriggeredSelect 变量为 false 时添加新条目的函数:
$scope.peopleSel= function(sel) {
if ( sel.search && ! sel.clickTriggeredSelect ) {
if ( ! sel.selected || sel.selected.name != sel.search ) {
//Search for an existing entry for the given name
var newOne= personSearch( sel.search );
if ( newOne === null ) {
//Create a new entry since one does not exist
newOne= { name: sel.search, email: 'none', country: 'unknown' };
$scope.people.push( newOne );
}
//Make the found or created entry the selected one
sel.selected= newOne;
}
}
sel.search= ''; //optional clearing of search pattern
};
请注意,此处未提供 personSearch 定义。此外,这种测试 clickTriggeredSelect 的方法可用于允许用户取消 select 如果空白条目是首选项的字段。
PVC
这里有一个解决方案:
HTML -
<ui-select ng-model="superhero.selected">
<ui-select-match placeholder="Select or search a superhero ...">{{$select.selected}}</ui-select-match>
<ui-select-choices repeat="hero in getSuperheroes($select.search) | filter: $select.search">
<div ng-bind="hero"></div>
</ui-select-choices>
</ui-select>
控制器 -
$scope.getSuperheroes = function(search) {
var newSupes = $scope.superheroes.slice();
if (search && newSupes.indexOf(search) === -1) {
newSupes.unshift(search);
}
return newSupes;
}
这里是 CodePen solution.
我已经分叉了 ui-select 项目以通过 allow-free-text 属性允许此功能
<ui-select allow-free-text="true" ng-model="ctrl.freeTextDemo.color2" theme="bootstrap" style="width: 800px;" title="Choose a color">
<ui-select-match placeholder="Select color...">{{$select.selected}}</ui-select-match>
<ui-select-choices repeat="color in ctrl.availableColors | filter: $select.search">
<div ng-bind-html="color | highlight: $select.search"></div>
</ui-select-choices>
</ui-select>
这是plnker
在 angular-ui 团队接受我的 pull request 之前,您可以获得 ui-select build,其中包括我在 my own repo
上的补丁我用keyup
添加了一个新的选项代表输入的文字。使用这种方法,如果用户按 enter
,他们可以 select 目前输入的内容(默认活动项目是第一个项目)。
当数据列表包含纯文本或对象(需要属性value-prop
)时,这两种情况都支持。
指令:
commonApp.directive("uiSelectFreeText", function () {
return {
restrict: "A",
require: "uiSelect",
link: function (scope, element, attrs, $select) {
var searchInput = element.querySelectorAll("input.ui-select-search");
if (searchInput.length !== 1) {
console.log("Error! Input not found.");
return;
}
searchInput.on("keyup", function () {
var valueProp = attrs["valueProp"];
var addNewObjOption = function () {
// add new item represent free text option
var newOption = { isFreeText: true };
newOption[valueProp] = $select.search;
$select.items.unshift(newOption);
};
if ($select.items.length > 0) {
var firstItem = $select.items[0];
if (valueProp) {
// items is list of Object
if (firstItem.isFreeText) {
firstItem[valueProp] = $select.search;
} else {
addNewObjOption();
}
} else {
// items is list of string
if (firstItem === $select.search) {
return;
} else {
$select.items.push($select.search);
}
}
} else {
if (valueProp) {
addNewObjOption();
} else {
// items is list of string
$select.items.push($select.search);
}
}
});
}
};
});
HTML:
<ui-select class="ui-select-control"
ui-select-free-text value-prop="Label"
ng-model="keyword">
</ui-select>