Autocompletar campos basados ​​en otro campo

10

Tengo una situación muy compleja en la que necesito algunos consejos. Tengo un tipo de contenido my_content, que tiene un campo de colección de campos adjunto field_mycollection, que tiene un campo de referencia de entidad que hace referencia al usuario field_my_userreference, un campo de teléfono field_my_phone, un campo de texto field_my_texty otro campo de texto field_my_anothertext.

My Content
|_ field_mycollection
   |_ field_my_userreference
   |_ field_my_phone
   |_ field_my_text
   |_ field_my_anothertext

La entidad de usuario también tiene campos field_my_phone, field_my_texty field_my_yetanothertexteste último tiene un nombre de máquina diferente.

Lo que quiero hacer, si se selecciona un my_contentformulario de edición / agregar, en field_my_userreferenceun usuario, los otros campos deben rellenarse automáticamente a partir de los datos del usuario seleccionado. Los campos autocompletados aún deben ser editables.

¿Cómo podría lograr este objetivo? Me gustaría hacerlo, si es posible, con algo de codificación, usando hook_form_FORM_ID_alter().

Елин Й.
fuente
¿Necesita que suceda en vivo en forma o en guardar?
Mołot
Vivir en forma. Ya lo he implementado para guardar, que los datos se tomarán de la entidad del usuario si se dejan vacíos. Pero en realidad lo que necesito en el formulario :(
Елин Й.
OK, planteé mi respuesta.
Mołot

Respuestas:

11

Si desea que suceda en vivo, y todos los campos ya están en el formulario, la forma más segura sería usarlo hook_form_FORM_ID_alter()para agregar lo siguiente a un formulario:

$form['#attached']['js'] = array(
  drupal_get_path('module', 'module_name') . '/js/copy_field_value.js',
);

Luego, en copy_field_value.jscrear comportamiento:

(function($) {
  Drupal.behaviors.moduleNameCopyFieldValue = {
    attach: function (context, settings) {

      // Repeat this for all fields as needed
      $('#source', context).on('blur', function () { 
        // above you can use change instead of blur if element is not changed by another js
        if (!$('#destination').val() || 0 === $('#destination').val().length) {
          $('#destination').val($(this).val());
          // wrap line above in "if no value" like I did, or other condition you like
        }
      });
      // end of "repeat this"
    }
  };
})(jQuery);

También puede usar hook_form_FORM_ID_alter()para agregar #ajaxparámetros al campo de origen, pero haría que su formulario llame a un servidor en cada copia de campo. Si realmente necesita consultar la base de datos, es el camino a seguir. Sería bastante amplio describirlo de nuevo aquí. Debe modificar la $form_state["input"]matriz para actualizar los valores reales que ve el usuario. Hágalo en la función de creación de formularios, envolviéndolo issetpara evitar avisos.

Si su elemento de formulario es $form["something"]["something"]["element"], su valor estará en $form_state["input"]["something"]["something"]["element"], y puede configurarlo hook_form_altercorrectamente, solo recuerde tomar ambos $formy $form_statepor referencia.

Nota : el .on()método se agregó en jQuery 1.7, por lo que necesitará jQuery Update para usar esta respuesta directamente o traducir mi código para usar .change()o .blur()método.

Mołot
fuente
Muchas gracias por las instrucciones! No estoy muy bien en la API JS de Drupal. ¿Podría explicar cómo obtengo los valores de campo de la entidad de usuario? Por ejemplo, si se selecciona un usuario, ¿cómo puedo completar los siguientes campos con la información de este usuario?
Елин Й.
1
@ ЕлинЙ. El truco aquí es no preocuparse por los antecedentes de PHP. Simplemente identifique los parámetros de <input>identificación de las etiquetas con Firebug o una herramienta similar para su navegador favorito. O use cualquier otro selector jQuery. Sucederá solo en el navegador, por lo que tiene lo que tiene en la pantalla. Por otro lado, si necesita consultar la base de datos (parece que me lo perdí), este #ajaxes el camino a seguir. Pero sería bastante amplio. Debe modificar la $form_state["values"]matriz para actualizar los valores reales que ve el usuario. Hágalo en la función de creación de formularios, envolviéndolo issetpara evitar avisos.
Mołot
Gracias de nuevo @ Mołot, intentaré implementarlo mañana, o tal vez esta tarde. Parece que necesitaré unas horas para que realmente funcione, si no más.
Елин Й.
@ ЕлинЙ. buena suerte, siéntase libre de regresar con más preguntas y vincularlas aquí en comentarios si están conectadas. Respuesta actualizada un poco, por cierto.
Mołot
1
Ok, lo experimentaré un poco y escribiré mis experiencias.
Елин Й.
4

Puedes hacerlo usando el módulo de campo calculado

Computed Field es un módulo de campo CCK muy potente que le permite agregar "campos calculados" personalizados a sus tipos de contenido. Estos campos calculados se completan con valores que usted define a través del código PHP. Puede recurrir a cualquier cosa disponible para Drupal, incluidos otros campos, el usuario actual, las tablas de la base de datos, lo que sea. (¿Siente el poder todavía? :)) También puede elegir si desea almacenar sus valores de campo calculados en la base de datos con otros campos de contenido o "calcularlos" sobre la marcha durante las vistas de nodo. (Aunque debe tener en cuenta que el uso de Vistas requiere valores almacenados en la base de datos). Este campo es literalmente la navaja suiza de los campos CCK. ¡Entonces comience a cocinar sus valores basados ​​en PHP!

4life
fuente
Gracias por la rápida respuesta. Suena muy prometedor. Sin embargo, no quiero instalar un módulo para eso, sino simplemente escribir algo de código, ya que necesito tal funcionalidad solo en ese formulario, y el sistema real ya es demasiado grande y muchos módulos están instalados para diversas funcionalidades.
Елин Й.
En segundo lugar, ¿es posible usar este módulo para que el usuario que está creando o editando el nodo anule los campos autocompletados manualmente y guarde? De modo que, en la entidad de usuario y my_content se guardan diferentes valores.
Елин Й.
Eso dependería de la forma en que se configura
4life
Gracias @ 4life, intentaré eso también si no puedo lograrlo con la codificación, siguiendo las instrucciones de Mołot.
Елин Й.
2

Quiero publicar cómo lo logré gracias a la gran ayuda de @ Mołot.

  1. Implementado el hook_form_FORM_ID_alter () .
  2. Se agregó un div de ajuste alrededor de la colección de campo.
  3. Dado que la colección my field es un campo de valores múltiples, itera sobre él y establece la #ajaxpropiedad para el campo field_my_userreference.
  4. Creó una función de devolución de llamada que simplemente devuelve el elemento de la colección de campos.
  5. Se verificó en la implementación hook_form_FORM_ID_alter (), si se establece $ form_state para la colección de campos. En caso afirmativo, obtenga los valores de la entidad de usuario y complete los campos de entrada del formulario con esos valores.

Mi código se ve así:

function MYMODULE_form_my_content_node_form_alter(&$form, &$form_state, $form_id) {
  $form['field_mycollection']['#prefix'] = '<div id="mycollection-wrapper">';
  $form['field_mycollection']['#suffix'] = '</div>';
  foreach ($form['field_mycollection']['und'] as $key => $fc_mycollection) {
    if (is_numeric($key)) {
      $form['field_mycollection']['und'][$key]['field_my_userreference']['und']['#ajax'] = array(
        'callback' => 'MYMODULE_mycollection_callback',
        'wrapper' => 'mycollection-wrapper',
      );
      if (isset($form_state['values']['field_mycollection']['und'][$key]['field_my_userreference']['und'][0]['target_id'])) {
        $user_wrapper = entity_metadata_wrapper('user', $form_state['values']['field_mycollection']['und'][$key]['field_my_userreference']['und'][0]['target_id']);
        $form_state['input']['field_mycollection']['und'][$key]['field_my_text']['und'][0]['value'] = $user_wrapper->field_my_text->value() ? $user_wrapper->field_my_text->value() : '';
        $form_state['input']['field_mycollection']['und'][$key]['field_my_anothertext']['und'][0]['value'] = $user_wrapper->field_my_text->value() ? $user_wrapper->field_my_yetanothertext->value() : '';
      }
    }
  }
}

function MYMODULE_mycollection_callback($form, &$form_state) {
  return $form['field_mycollection'];
}
Елин Й.
fuente