2010-07-21 25 views
11

Tengo muchos problemas para hacer que el widget de autocompletar de jQuery funcione para mí. Estoy usando una lista de pares clave/valor de un servidor.jQuery UI Autocompletar con texto híbrido/búsqueda de id

que tienen los siguientes requisitos:

Si el usuario selecciona un valor desde el widget, que quiero pasar el ID al servidor.

Si el usuario no selecciona un valor e ingresa el texto sin formato, o modifica un valor que ya ha sido seleccionado, quiero que se borre el campo de ID y que el texto sin procesar sea enviado al servidor.

Suponga que someAjaxFunction devuelve una matriz de objetos que el widget de autocompletar espera: {label:label, value:key}.

Inicialmente conjunto de widgets del autocompletar hasta este modo:

$(input).autocomplete({ 
    source: sourceFunction, 
    minLength: 1 
}); 

Cambio de la selección, incluso colocando el cursor sobre uno de los elementos cambia el texto en el cuadro de texto referenciado por $ (entrada) a la clave subyacente, en lugar de la etiqueta. Esto es altamente indeseable desde el punto de vista de la interacción del usuario; de hecho, la razón por la que estoy investigando esto es porque los usuarios del sitio que estoy creando se desconcertaron constantemente por el texto que ingresaron y que aparentemente se convirtió en números aleatorios.

he añadido un campo oculto bajo el cuadro de texto e implementó el select() y el enfoque() eventos con el fin de ocultar el ID de este modo:

$(input).autocomplete({ 
    source: sourceFunction, 
    minLength: 1 
    focus: function(event, ui) { 
     $(idField).val(ui.item.value); 
     $(this).val(ui.item.label); 
     return false; 
    }, 
    select: function(event, ui) { 
     $(idField).val(ui.item.value); 
     $(this).val(ui.item.label); 
     return false; 
    }, 
    minLength: 1 
}); 

Esto funciona bien cuando el usuario se está pegando a la secuencia de comandos proporcionada por el menú desplegable Autocompletar. El ID está oculto y enviado correctamente al servidor. Lamentablemente, si el usuario desea ingresar texto de forma libre en el cuadro y buscar según ese valor, el campo ID no se restablece y el ID seleccionado previamente se envía al servidor. Esto también es bastante confuso.

La documentación de jQuery UI autocompletar enumera un evento change y establece que la propiedad item del argumento ui será ajustado en el elemento seleccionado. Pensé que podría restablecer el campo de identificación oculto al presionar una tecla y volver a llenar la ID si se modifica la función Autocompletar. Desafortunadamente, además del evento de pulsación de tecla que captura un montón de pulsaciones de teclas que no debe restablecer el ID, la instrucción return false en el evento select anterior que es necesario para administrar el texto en el cuadro de texto impide que el evento change tenga ui .item correctamente asignado.

Así que ahora estoy atascado, realmente no sé qué más puedo intentar para hacer que la funcionalidad de soporte de widgets parezca que debería ser compatible por defecto. O este proceso es mucho más complicado de lo que debería ser, o me falta algo realmente obvio. Recogí todos los eventos disponibles y todos los ejemplos, y salgo con las manos vacías. De hecho, incluso el ejemplo "Datos y visualización personalizados" en la página de jQuery UI sufre este problema.

Puedo agregar algunos hacks en el lado del servidor para cubrir esto, pero realmente preferiría poder hacerlo a nivel del cliente.

También preferiría seguir el widget de autocompletar jQuery UI en lugar de cambiar a otro.

+0

Disculpa, ¿puedo aclarar algo? Al menos uno de sus problemas es que desea que el cuadro de identificación se complete con * la * identificación asociada si el usuario ingresa un valor que tiene una ID correspondiente, o lo que el usuario escriba, si no hay un valor correspondiente - correcto/¿incorrecto? – Stephen

+0

No, solo quiero que el campo ID oculto esté vacío si el texto en el cuadro de texto está configurado a algo que no corresponde a una selección ofrecida por la función autocompletar. – Shabbyrobe

Respuesta

2

La forma en que estoy haciendo autocompletar, es crear un contenedor div que contiene la entrada.Cuando selecciono un elemento, agrego un enlace que contiene un tramo al contenedor y oculto el cuadro de entrada.

El enlace y el tramo están diseñados para que parezca un botón, con una X, y tiene un controlador de evento de clic para eliminar la entrada del DOM, borrar el campo oculto y volver a mostrar el cuadro de entrada al hacer clic . Así que cuando se selecciona un artículo:

<div class="container"> 
    <a href="#"><span>Selected Item</span></a> 
    <input id="myautocomplete" type="text" /> 
    <input type="hidden" name="myvalue" value="1" /> 
    </div> 

Y cuando un elemento no está seleccionado:

<div class="container"> 
    <input id="myautocomplete" name="myautocomplete" type="text" /> 
    <input id="myvalue" name="myvalue" type="hidden" value="" /> 
    </div> 

De esta manera, se ven obligados, ya sea para seleccionar un elemento, o que introduzca texto de forma libre. En el backend, si el parámetro de solicitud con la clave 'myvalue' está vacío, entonces debería mirar el parámetro de solicitud con la clave 'myautocomplete'.

+0

también, en el controlador de selección de la autocompletar jQuery UI, cada vez que seleccione un elemento, podría crear un campo oculto con el mismo nombre, por lo que si está seleccionando varios países, cree el nombre del campo oculto 'países'. Si hace clic en una entrada para eliminarla, se elimina el campo oculto asociado. En el lado del servidor, terminas recuperando una lista de identificadores separados por comas que deben dividirse y convertirse en una matriz entera/larga. – jamiebarrow

+0

Esta es una gran sugerencia y, a falta de algo más simple, es lo que yo haré. Sin embargo, idealmente, preferiría algo que requiera mucho menos construir sobre el widget jQuery UI: me parece que el widget debería soportar lo que quiero hacer más o menos de la caja. – Shabbyrobe

+0

Bueno, me han encargado algo similar, así que también estaba buscando sugerencias sobre cómo hacerlo bien :) Me alegra que mi sugerencia haya sido útil. Otra cosa es si uno está usando la misma página para crear y editar; al volver a cargar la página mientras edita, debe recrear todos los tramos, etc. para los valores en el campo oculto. Por el momento solo estoy haciendo esto en el lado del servidor. El único problema es que cosas como las clases que se usan ahora deben mantenerse en el código de la interfaz y en el código de backend ... No me gusta, pero funciona. – jamiebarrow

1

Cuando yo supongo que se han fijado los siguientes campos:

<div> 
    <input type="text" name="visible" class="autocomplete-reference" /> 
    <input type="hidden" name="hidden" /> 
</div> 

Necesitas init siguiente js (funciona con jQuery 1.5.2):

$(document).ready(function() { 
    $('.autocomplete-reference').each(function() { 
     $(this).keydown(function(e){ 
      /* 
      * this will reset hidden id reference on each visible field manual change 
      * we have to bind it on keydown because we want to recognize event of submiting form by enter after autocomplete set 
      */ 
      if (e.keyCode != 13) { 
       $(this).siblings('input[type=hidden]').each(function() { 
        $(this).val(''); 
       }); 
      } 
     }); 
     $(this).autocomplete({ 
      minLength: 1, 
      /* you can set appending of autocomplete menu into some container to set css contextually 
      appendTo: '#someElem',*/ 
      source: sourceFunction, 
      search:function (event, ui) { 
       //TODO ...spinner init... 
      }, 
      open:function (event, ui) { 
       /* you can grab autocomplete menu widget by this to manipulate some recognizing id, etc.. 
       * $(this).autocomplete('widget') 
       */ 
       //TODO ..stop spinner ... 
       $(this).keydown(function(e){ 
        /* this is important for live reference updates while arrow keys changes */ 
        if (e.keyCode == 37 || e.keyCode == 39) { 
         $($(this).data('autocomplete').menu.active).find('a').trigger('click'); 
        } 
       }); 
      }, 
      focus: function(event, ui) { 
       /* here we'll map our data object onto both fields */ 
       $(this).val(ui.item.label); 
       $(this).siblings('input[type=hidden]').each(function() { 
        $(this).val(ui.item.key); 
       }); 
      }, 
      select: function(event, ui) { 
       /* here we'll map our data object onto both fields */ 
       $(this).val(ui.item.label); 
       $(this).siblings('input[type=hidden]').each(function() { 
        $(this).val(ui.item.key); 
       }); 
      }, 
      close: function(event, ui) { 
       //TODO ..stop spinner ... 
      } 
     }); 
    }); 
}); 

Es muy bueno tener un poco validación en el servidor que puede convertir exactamente: valores de campo visibles en referencias para gente de tipeo rápido, por supuesto.

0

Aunque es una vieja pregunta, mi método puede ayudar.

En el evento .change puede buscar el valor del cuadro de texto con el valor en de su lista Fuente utilizando el bucle.

Ir a más detalles: Aquí está en la lista de fuentes de Ajax, pero el entrenamiento es similar. Search a text In Jquery AutoComplete Ui

Esta cosa me había estado molestando muchas veces y, finalmente, ahora he descubierto :)

0

Puede utilizar event.preventDefault

Recoger sus valores seleccionados a través ui.item.label o ui.item.value y obtenga el valor necesario y configúrelo en el mismo cuadro de texto.

var idNameCombo = ui.item.label; 
      event.preventDefault(); 
      $("#mID").val(idNameCombo.split(",")[0].trim()); 
Cuestiones relacionadas