Автозаполнение полей на основе другого поля

10

У меня очень сложная ситуация, когда мне нужен совет. У меня есть тип контента my_content, к которому прикреплено поле коллекции полей field_mycollection, в котором есть поле ссылки на сущность, ссылающееся на пользователя field_my_userreference, телефонное поле field_my_phone, текстовое поле field_my_textи другое текстовое поле field_my_anothertext.

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

Пользовательский объект также имеет поля field_my_phone, field_my_textи field_my_yetanothertextпоследний из них имеет другое имя компьютера.

Что я хочу сделать, если в my_contentформе редактирования / добавления field_my_userreferenceвыбран пользователь, остальные поля должны быть автоматически заполнены из данных выбранного пользователя. Автоматически заполненные поля должны быть доступны для редактирования.

Как я мог достичь этой цели? Я хотел бы сделать это, если это возможно, с некоторым кодированием, используя hook_form_FORM_ID_alter().

Елин Й.
источник
Вам нужно, чтобы это происходило вживую в форме или при сохранении?
Молот
Жить на форме. Я уже реализовал это, что при сохранении, что данные будут взяты из объекта пользователя, если оставить пустым. Но на самом деле то, что мне нужно в форме :(
Елин Й.
ОК, поставил мой ответ.
Молот

Ответы:

11

Если вы хотите, чтобы это происходило вживую и все поля уже были в форме, самым безопасным способом было бы hook_form_FORM_ID_alter()добавить следующие элементы в форму:

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

Тогда в copy_field_value.jsсоздании поведения:

(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);

Вы также можете использовать hook_form_FORM_ID_alter()для добавления #ajaxпараметра в исходное поле, но это сделает вашу форму для вызова сервера для каждой копии поля. Если вам нужно на самом деле запросить базу данных, это путь. Было бы довольно широко описать это здесь заново. Вам нужно изменить $form_state["input"]массив, чтобы обновить реальные значения, увиденные пользователем. Сделайте это в функции создания формы, оборачивая ее, issetчтобы избежать уведомлений.

Если ваш элемент формы $form["something"]["something"]["element"], его значение будет в $form_state["input"]["something"]["something"]["element"]- и вы можете установить его в hook_form_alterпорядке, просто не забудьте взять оба $formи $form_stateпо ссылке.

Примечание : .on()метод был добавлен в jQuery 1.7, поэтому вам понадобится jQuery Update, чтобы напрямую использовать этот ответ или перевести мой код для использования .change()или .blur()метода.

МОЛОТ
источник
Большое спасибо за инструкции! Я не очень хорошо разбираюсь в JS API Drupal. Не могли бы вы объяснить, как я могу получить значения полей от объекта пользователя? Например, если выбран пользователь, как я могу заполнить следующие поля информацией этого пользователя?
Елин Й.
1
@ ЕлинЙ. Хитрость здесь не в том, чтобы заботиться о фоне php. Просто идентифицируйте параметры идентификаторов <input>тегов, используя Firebug или аналогичный инструмент для вашего любимого браузера. Или используйте любой другой селектор jQuery. Это произойдет только в браузере, поэтому у вас есть то, что у вас есть на экране. С другой стороны, если вам нужно на самом деле запросить базу данных (кажется, я пропустил это), #ajaxэто путь. Но это было бы довольно широко. Вам нужно изменить $form_state["values"]массив, чтобы обновить реальные значения, увиденные пользователем. Сделайте это в функции создания формы, оборачивая ее, issetчтобы избежать уведомлений.
Молот
Еще раз спасибо @ Молот, я постараюсь реализовать это завтра или, может быть, сегодня вечером. Кажется, мне понадобится несколько часов, чтобы все заработало, если не больше.
Елин Й.
@ ЕлинЙ. удачи, не стесняйтесь возвращаться с дополнительными вопросами и связывать их здесь в комментариях, если они связаны. Обновленный ответ немного, кстати.
Молот
1
Хорошо, я немного поэкспериментирую и напишу свой опыт.
Елин Й.
4

Вы можете сделать это с помощью модуля вычисляемых полей

Computed Field - очень мощный модуль поля CCK, который позволяет добавлять пользовательские «вычисляемые поля» к типам контента. Эти вычисляемые поля заполняются значениями, которые вы определяете с помощью кода PHP. Вы можете использовать все, что доступно для Drupal, включая другие поля, текущего пользователя, таблицы базы данных, назовите это. (Чувствуете силу еще? :)) Вы также можете выбрать, сохранять ли свои вычисленные значения полей в базе данных вместе с другими полями контента или же они «вычисляются» на лету во время просмотра узлов. (Хотя вы должны заметить, что для использования Views требуются значения, хранящиеся в базе данных.) Это поле буквально является швейцарским армейским ножом полей CCK. Так что начните готовить свои значения на основе PHP!

4life
источник
Спасибо за быстрый ответ. Это звучит очень многообещающе. Хотя я не хочу устанавливать модуль для этого, а просто пишу некоторый код, поскольку мне нужна такая функциональность только в этой форме, а реальная система уже слишком большая, и многие модули установлены для различных функций.
Елин Й.
Во-вторых, возможно ли использовать этот модуль для пользователя, который создает или редактирует узел, чтобы переопределить автоматически заполненные поля вручную и сохранить? Так что в user entity и my_content сохраняются разные значения.
Елин Й.
Это будет зависеть от того, как это настроено
4life
Спасибо @ 4life, я тоже попробую, если не смогу добиться этого с помощью кодирования, используя инструкции Mołot.
Елин Й.
2

Я хочу опубликовать, как я достиг этого благодаря большой помощи @ Mołot.

  1. Реализован hook_form_FORM_ID_alter () .
  2. Добавлен упаковочный div вокруг коллекции полей.
  3. Поскольку коллекция my field является многозначным полем, выполните итерацию по нему и установите #ajaxсвойство для поля field_my_userreference.
  4. Создана функция обратного вызова, которая просто возвращает элемент коллекции полей обратно.
  5. Проверяется в реализации hook_form_FORM_ID_alter (), если для коллекции полей установлено значение $ form_state. Если да, получите значения из пользовательского объекта и заполните поля ввода формы этими значениями.

Мой код выглядит так:

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'];
}
Елин Й.
источник