Приветствую
Кастомизирую форму ноды, вывожу select
После отправки формы вызываю
$output = ctools_modal_form_wrapper('train_node_form', $form_state);
Выбранное пользователем значение попадает в $form_state['values']['field_group'] и имеет строковый тип. И значение не попадает в базу
В случае если не изменять $form['field_group'] то в $form_state['values']['field_group'] содержится массив ['und'][0]['target_id'] и тогда всё нормально сохраняется.
Всю голову сломал, что я делаю не так?
Комментарии
Что такое hook_form и при чем тут ctools? Хотите что-то поправить в форме, то нужно делать hook_form_alter(&$form, &$form_state, $form_id) Ловить идешник вашей формы и переопределить значение, какое вам нужно.
Потому что в $form_state['values']['field_group'] должен быть массив: ['und'][0]['target_id'].
Выводите select не в $form ['field_group'],а в $form ['field_group']['und'][0]['target_id'].
Только туда нужно выводить не тот массив, который в примере, а массив именно терминов. А вместо 'und' нужно писать LANGUAGE_NONE
лучше уж тогда ознакомиться с правильной работой с полями, в том числе и с языками полей http://drupalace.ru/lesson/korrektnaya-rabota-s-polyami-v-sedmom-drupale...
Спасибо за ответы
Конкретизирую. Написал модуль (напр schedule), через schedule_node_info создал для него тип материала (train).
Мне нужно чтобы поле группа фильтровалось в зависимости от значения другого поля на форме (дисциплина). Поэтому я добавил функцию train_form и в ней прописал
'#type' => 'select',
'#title' => t('Группа'),
'#options' => $groups[ $discipline_id ],
'#default_value' => $group->nid,
'#maxlength' => 127,
'#prefix' => '<div id="field-group-replace">',
'#suffix' => '</div>',
Плюс добавил select для выбора самой дисциплины, другие поля на форме я не объявлял и друпал я так понимаю для них сам создал контролы.
Теперь если я сохраняю форму то те поля которые автоматически добавлены друпалом сохраняются в БД, а группа нет.
Я понимаю что можно через metadata wrappers сохранить вручную, но мне кажется это неправильным.
Может я вообще всё делаю неправильно.
Я попробовал через hook_form_alter в $form ['field_group']['und'] прописать массив описывающий select, но это никак не отразилось на форме.
Если вы создали новую форму для контент тайпа, то с чего вы взяли, что друпал что-то об этом знает, а тем более, что-то сам добавит в базу?
Чтобы в базу происходила автоматическая запись, то поле нужно объявлять в сущности типа материала. Да и куда ему писать-то, если таблица для группы не было создана (если я вас правильно понял, то вы не создавали поле группа в материале). А для того, чтобы сделать зависимые поля, то нужно использовать либо form_state, либо form_ajax (что предпочтительней). Либо использовать модуль conditions.
Я мог вас не правильно понять. Но вы и не можете четко сформулировать свою проблему. Вы должны были сообщить, что создали такой-то материал, с такими-то полями. Потом хотите сделать то-то, и получить что-то. А вы все крутитесь вокруг своей form group. Но никто не может прочитать ваши мысли!
Все необходимые поля я создал в админке. Все они по submit сохранялись. Дальше мне нужно было изменить порядок заполнения поля Группа. Я объявил hook_form и в $form ['field_group'] запихнул своё описание select'а . Теперь это поле не сохраняется.
Можно подробнее?Код сейчас имеет такой вид
{
// cut...
$items['fcschedule/%ctools_js/add_train/%node/%/%'] = array(
'page callback' => 'fcschedule_node_add_modal_callback',
'page arguments' => array(1, 3, 4, 5),
'access arguments' => array('access content'),
);
return $items;
}
function fcschedule_node_info()
{
return array(
'train' => array(
'name' => t('Занятия'),
'base' => 'train',
'description' => t('Занятия'),
)
);
}
function fcschedule_node_add_modal_callback($js = FALSE, $group, $date, $time) {
global $user;
// If people aren't using javascript, then I just boot em. sorry. its 2011.
if (!$js) return "Javascript required";
// Include your ctools crap here
ctools_include('node.pages', 'node', '');
ctools_include('modal');
ctools_include('ajax');
// Create a blank node object here. You can also set values for your custom fields here as well.
$node = (object) array(
'uid' => $user->uid,
'name' => (isset($user->name) ? $user->name : ''),
'type' => 'train',
'language' => LANGUAGE_NONE,
);
$form_state = array(
'title' => t('Add my conten type'),
'ajax' => TRUE,
);
$form_state['build_info']['args'] = array($node);
$form_state['build_info']['args']['param_group'] = $group;
$form_state['build_info']['args']['param_date'] = $date;
$form_state['build_info']['args']['param_time'] = $time;
// change this to your type node form
$output = ctools_modal_form_wrapper('train_node_form', $form_state);
// This means the form has been exectued
if (!empty($form_state['executed'])) {
$output = array();
// Close the modal
$output[] = ctools_modal_command_dismiss();
$output[] = ajax_command_invoke('#shed2-refresh', 'click');
}
print ajax_render($output);
exit;
}
function train_form($node, &$form_state) {
module_load_include('inc', 'fcschedule', 'fcschedule');
$form = array();
$discips = FCShedule::getDisccipArray();
$groups = FCShedule::getGroupsArray();
if (isset($form_state['build_info']['args']['param_group'])) {
$group = $form_state['build_info']['args']['param_group'];
}
else {
$node = node_load($node->nid);
$group = node_load($node->field_group);
}
$discipline_id = isset($form_state['values']['discipline']) ? $form_state['values']['discipline'] : $group->field_discipline[LANGUAGE_NONE][0]['target_id'];
$form ['discipline'] = array(
'#type' => 'select',
'#title' => t('Дисциплина'),
'#options' => $discips,
'#default_value' => $discipline_id,
'#maxlength' => 127,
'#ajax' => array(
'event'=>'change',
'callback' => 'fcschedule_train_discip_change_callback',
'wrapper' => 'field-group-replace',
),
);
$form ['field_group'] = array(
'#type' => 'select',
'#title' => t('Группа'),
'#options' => $groups[ $discipline_id ],
'#default_value' => $group->nid,
'#maxlength' => 127,
'#prefix' => '<div id="field-group-replace">',
'#suffix' => '</div>',
);
return $form;
}
function fcschedule_train_discip_change_callback($form, $form_state) {
return $form['field_group'];
}
Момент номер один. Я не вижу логику работы аякса. Он просто возвращает сам себя, грубо говоря. В $group->nid по умолчанию у вас всегда константа, которую вы тянете из аргументов $form_state, которые туда попали при построении динамического окна. Вам нужно создать валидацию элемента, в которой вы сможете построить свою логику для аякса. Например, запихнуть в $form_state новые данные, которые вам нужны.
Момент номер два. Что значит изменить порядок заполнения? Точнее скажите. Если у вас уже есть созданный материал с двумя полями группы и дисциплины, то вам незачем городить такой огород с инициализацией материала и инициализацией для него полей.
Зачем function train_form($node, &$form_state), если вы поля создали вручную? Тем более, что в диалоговое окно вы передаете форму друпала.
Спасибо
Идея следующая, есть ноды занятия, группы, дисциплины. В ноде занятия есть поле группа, а каждая группа ссылается на дисциплины:Группа 1 - Танцы
Группа 2 - Танцы
Группа 1 - Бокс
Группа 2 - Бокс
Если в форму занятия вывести группы селектом, то получится список Группа 1, Группа 2, Группа 1, Группа 2. Пытался через "Entity Reference View Widget" но во-первых долго набивка материала производится, во-вторых, закрывая модальное окно выбора группы (View Widget) сразу закрывается и модальное окно редактирования занятия. Как решить я не понял и остановился на варианте с 2мя селектами, в первый я вывожу все дисциплины, а группы уже по ней фильтрую
Пример я этот взял от сюда https://gist.github.com/mrconnerton/1979037 . Перезаполнение списков работает нормально, сначала вызывается train_form, если указали дисциплину, то в #options списка групп попадают групп только по ней. Следом за ней вызывается fcschedule_train_discip_change_callback который возвращает только что сформированный массив field_groupС $group->nid похоже действительно ошибка, но это влияет только на #default_value списка групп. Вот тут я честно говоря совсем не понял. Поля я создал в базе, в train_form для этого типа материала я описываю форму.
Если вы создали поля в материале, который уже существует, то вам никакую форму описывать вообще не нужно. Она уже создана друпал. Тот хук, что вы пытаетесь использовать, это наследие шестой версии, которое уже не используется в семерке. В колбеке вызова диалогового окна у вас происходит вызов уже существующей формы: $output = ctools_modal_form_wrapper('train_node_form', $form_state); Вы какую форму вызываете? Правильно: train_node_form, а не train_form. Но объявив train_form вы вмешались в работу формы и переопределили ее. Кстати, название не правильное. Да и если вы сами создали материал, то нет смысла хук инфо создавать. Хотели из модуля создать материал с полями? Нужно было это через сущности делать. Да то такое.
Тут ошибка вообще в построении архитектуры! Группы - это таксономия! Дисциплины - это тоже таксономия! А занятия уже ноды.
Например:
Спорт
-Бокс
-Плавание
-Футбол
Гуманитарные науки
-Поэзия
-Философия
У вас тут получается иерархический словарь таксономии! Где группы - это первая вложенность, а дисциплины - вторая.
Материал занятия уже содержит подробное описание и другие поля. Создается нода занятия. Выбирается Term reference из словаря таксономии Спорт (если список иерархического выбора), появляется новое поле - выбираете Плавание. ВСЕ!!!!
Теперь вы можете в последствии производить поиск, сортировку, фильтрацию, как вам будет угодно.
Спасибо за развёрнутый ответ
Не знал, в документации об этом ни слова, а с 6кой я не связывалсяМатериал создал модуль, а поля я уже сам накидал. Вообще hook_node_info я бы и не объявлял, просто, как я понял, он нужен для hook_form.
Спасибо, сначала хотел сделать через таксономию, сейчас уже не вспомню почему переиграл. Про иерархически словарь даже не думал
Ещё раз спасибо.
Не за что. Удачи вам.