javascript - ejemplos - Selección ui angular que filtra solo un campo
angularjs example (4)
He visto unos cuantos flotando como la respuesta de kunsingh, lo que me permitió comenzar a resolver mi problema similar. En mi caso, estaba buscando en múltiples objetos y en objetos, pero también envío registros eliminados de forma lógica al cliente y, opcionalmente, los filtro en listas. Para los menús desplegables quería que siempre se eliminaran sin tener que modificar la API.
Aquí está mi versión alterada, que incluye la búsqueda de objetos. Obviamente, esto solo funcionará si todas sus tablas tienen una columna int denominada Eliminada (para mí es parte de la clave única y se establece en el valor de identidad cuando se elimina), y se la pasa al cliente.
En un momento posterior, planeo realizar modificaciones adicionales para permitir la búsqueda recursiva de objetos.
App.filter(''dropdownFilter'', function () {
return function (items, props: Object, keyvalue?) {
var out = [];
if (angular.isArray(items)) {
items.forEach(function (item) {
var itemMatches = false;
var canbreak = false;
// Filter out logically deleted records
if (item.Deleted != 0)
itemMatches = false;
else {
var keys = Object.keys(props);
for (var i = 0; i < keys.length; i++) {
var prop: string = keys[i];
var text = "";
// If an object, e.g. searching deep, such as Project: {ProjectName: $select.search}
// Then iterate through the object to find values.
// NOTE: This one searches one deep from each object,
// e.g. Project.ProjectName
// Project.User.LastName WILL NOT WORK.
if (angular.isObject(props[prop])) {
angular.forEach(props[prop], function (value, key) {
text = value.toLowerCase();
if (item[prop][key].toLowerCase().indexOf(text) !== -1) {
itemMatches = true;
canbreak = true;
}
});
if (canbreak)
break;
}
// If it''s a simple array, then woo!
else {
text = props[prop].toLowerCase();
if (item[prop] != undefined && 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;
}
});
y una muestra de ella en uso (utilizando select2 para angular). Este es un menú desplegable de estado / país con país como subobjeto de estado.
<ui-select ng-model="personneladdress.StateID" theme="select2" class="select2">
<ui-select-match placeholder="{{language.State}}">{{$select.selected.StateName}}</ui-select-match>
<ui-select-choices repeat="item.StateID as item in State | dropdownFilter: {StateName: $select.search, Country: {CountryName: $select.search}}">
<span ng-bind-html="item.StateName | highlight: $select.search"></span><br />
<small>
<span ng-bind-html="''''+item.Country.CountryName | highlight: $select.search"></span>
</small>
</ui-select-choices>
</ui-select>
LA SITUACIÓN:
Tengo una aplicación angular utilizando ui-select angular para buscar y seleccionar personas de una base de datos.
Está funcionando bien, excepto una cosa. El usuario debe poder filtrar entre las personas utilizando dos criterios: nombre y correo electrónico.
Usando el filtro angular normal, puedo filtrar solo uno de ellos. Si trato de filtrar ambos campos, ya no funciona.
EJEMPLO DE TRABAJO CON UN CAMPO:
<ui-select multiple ng-model="database_people.selectedPeople" theme="select2" ng-disabled="disabled" style="width:100%">
<ui-select-match placeholder="Select person...">{{$item.name}} < {{$item.email}} ></ui-select-match>
<ui-select-choices repeat="person2 in list_people | filter: {name: $select.search, db_data_type_id: 5}">
<div ng-bind-html="person2.name | highlight: $select.search"></div>
<small>
email: <span ng-bind-html="''''+person2.email | highlight: $select.search"></span>
</small>
</ui-select-choices>
</ui-select>
NO FUNCIONA EJEMPLO CON DOS CAMPOS EN EL FILTRO:
<ui-select multiple ng-model="database_people.selectedPeople" theme="select2" ng-disabled="disabled" style="width:100%">
<ui-select-match placeholder="Select person...">{{$item.name}} < {{$item.email}} ></ui-select-match>
<ui-select-choices repeat="person2 in list_people | filter: {name: $select.search, email: $select.search, db_data_type_id: 5}">
<div ng-bind-html="person2.name | highlight: $select.search"></div>
<small>
email: <span ng-bind-html="''''+person2.email | highlight: $select.search"></span>
</small>
</ui-select-choices>
</ui-select>
Lo extraño es que en realidad funciona PERO solo para el primer personaje. Cuando escribo el primer carácter, lo resalta en ambos campos, nombre y correo electrónico. Pero cuando escribo el segundo carácter ya no funciona (no tengo ningún error en la consola).
INTENTAR EL USO DE PROPSFILTER DE MUESTRAS ANGULARES:
<ui-select multiple ng-model="database_people.selectedPeople" theme="select2" ng-disabled="disabled" style="width:100%">
<ui-select-match placeholder="Select person...">{{$item.name}} < {{$item.email}} ></ui-select-match>
<ui-select-choices repeat="person2 in list_people | propsFilter: {name: $select.search, email: $select.search, db_data_type_id: 5}">
<div ng-bind-html="person2.name | highlight: $select.search"></div>
<small>
email: <span ng-bind-html="''''+person2.email | highlight: $select.search"></span>
</small>
</ui-select-choices>
</ui-select>
En este caso, se rompió por completo, ya no hay datos en el select2 y recibo algunos errores en la consola:
Cannot read property ''toString'' of null
Cannot read property ''length'' of undefined
LAS PREGUNTAS):
¿Cómo puedo filtrar entre varios campos? ¿Puedo hacer eso usando filtro normal? ¿O tengo que usar un filtro personalizado? Pero en este caso, ¿por qué no funciona correctamente?
¡Muchas gracias!
Puedes usar el filtro de propiedades como abajo
<ui-select ng-model="emplyee" theme="bootstrap">
<ui-select-match placeholder="Select ...">{{$select.selected.firstName+" "+$select.selected.lastName}}</ui-select-match>
<ui-select-choices repeat="emp in employees | propertyFilter: {firstName:$select.search, lastName:$select.search}">
<span ng-bind-html="emp.firstName+'' ''+emp.lastName | highlight: $select.search"></span>
</ui-select-choices>
Tendrás que modificar el propertyFilter como a continuación:
.filter(''propertyFilter'', function($log) {
return function(items, props) {
var out = [];
if (angular.isArray(items)) {
items.forEach(function(item) {
var itemMatches = false;
var keys = Object.keys(props);
var optionValue = '''';
for (var i = 0; i < keys.length; i++) {
optionValue = item[keys[i]] ? optionValue + item[keys[i]].toString().toLowerCase().replace(/ /g, '''') : '''';
}
for (var j = 0; j < keys.length; j++) {
var text = props[keys[j]].toLowerCase().replace(/ /g, '''');
if (optionValue.indexOf(text) !== -1) {
itemMatches = true;
break;
}
}
if (itemMatches) {
out.push(item);
}
});
} else {
// Let the output be the input untouched
out = items;
}
return out;
};
})
La búsqueda se puede hacer en el valor de las opciones en su conjunto. Por ejemplo, si en opciones tienes ''peter parker'', puedes buscar con ''peter'', ''parker'', ''peter parker'', ''peterparker'' e incluso buscar con múltiples espacios entre cualquier personaje de peter parker.
Resolví este problema usando este pedazo de código:
<ui-select-choices repeat="person2 in list_people | filter: $select.search" >
En ui-select-match yo uso dos campos:
<ui-select-match placeholder="select One...">
{{$item.field1}} - {{$item.field2}}
</ui-select-match>
Tal vez sea porque el mismo valor ($ select.search) se usa para los filtros correo electrónico y nombre.
<ui-select-choices repeat="person2 in list_people | filter: {name: $select.search, email: $select.search, db_data_type_id: 5}">
...
Esto también explica, por qué solo funciona con el primer carácter.
Use valores separados para cada filtro para arreglar esto:
<ui-select-choices repeat="person2 in list_people | filter: {name: $select.search.name, email: $select.search.email, db_data_type_id: 5}">
...