Как подставить поле формы в нужное место?

Аватар пользователя maiskiykot maiskiykot 8 марта в 14:29

Понадобилось в форме сделать программно кнопку для генерации пароля. И никак не могу понять: как эту кнопку привязать к полям формы? Если ставлю weight, то вроде как попадает в форму кнопка, но то выше сильно, то сильно ниже при изменении веса. Отрицательный пробовал ставить вес - та же фигня. Подскажите: что тут не так?

Лучший ответ

Аватар пользователя charOFF charOFF 9 марта в 15:19

Вам надо внимательно посмотреть вывод dpm формы внутри функции форм альтера, найти там поле, перед которым надо вставить кнопку. Оно может быть и не на верхнем уровне. Например, поле пароль в форме регистрации находится внутри контейнера 'account', т.е. в $form['account']['pass']. Если так, то надо вставлять 'changethis' не в $form, а в $form['account'].
По поводу весов - тоже надо смотреть. В той же форме регистрации, веса для элементов внутри $form['account'] по-умолчанию не заданы и рендерятся в порядке следования в массиве. В этом случае нужно массив $form['account'] перебирать и назначать всем элементам нужный вес. Тогда можно будет осмысленно вставить кнопку в нужное место.

Комментарии

Аватар пользователя ivnish ivnish 8 марта в 15:53

Может проще сделать шаблон для формы и там уже разместить элементы в удобном виде?

Аватар пользователя maiskiykot maiskiykot 8 марта в 16:13

У меня несколько вариантов формы ввиду нескольких ролей пользователей. Замучаешься формы создавать. И разве у профиля есть шаблон?

Аватар пользователя OldWarrior OldWarrior 8 марта в 16:03

1. Поля, к которым пытаетесь прилепить кнопку, могут быть объединены в виджет. Стало быть, вставить кнопку по её весу между полями виджета не получится.

2. Поля программной формы по умолчанию могут не иметь явного веса. В таком случае поля будут выводиться в той последовательности, в какой они объявлены в массиве формы. И, скорее всего, их вес будет интерпретироваться как 0 (всех). И если вы укажите явно вес для своей кнопки (например, 1), то ваш элемент будет заведомо ниже этой группы. Выход: хуком перебирать существующие поля формы и принудительно ставить им вес.

Аватар пользователя maiskiykot maiskiykot 8 марта в 16:13

Я посмотрел devel - у каждого поля есть свой вес. В принципе, вес срабатывает, но вот все как-то невпопад

Аватар пользователя OldWarrior OldWarrior 8 марта в 16:54

Вообще - слишком много невнятных вводных.
Лучше бы всего весь код - и формы и ваш - выложить в студию.

Аватар пользователя maiskiykot maiskiykot 8 марта в 19:01

Так форма - профиль пользователя. Стандартный. А вставка -
$form['changethis'] = array(
'#prefix' => '',
'#suffix' => '',
'#type' => 'button',
'#value' => 'Сгенерировать пароль',
'#weight' => 8,
'#ajax' => array(
'callback' => 'shiny_dynamic_form_ajax_callback',
'wrapper' => 'replace_textfield_div',
),
);

Аватар пользователя maiskiykot maiskiykot 8 марта в 19:59

А как это относится к позиционированию? Моя процедура работает отменно. Вопрос только в том: как вывести кнопку возле определённого поля. К примеру поле пароль.

Аватар пользователя OldWarrior OldWarrior 8 марта в 21:20

Я уже писал выше про виджеты, но видимо это не ваш случай. А так - альтерить виджет уместнее hook_field_widget_form_alter

Аватар пользователя OldWarrior OldWarrior 8 марта в 21:25

Выложили бы, что ли, хотя бы вывод dpm формы
Хотя и это вряд ли существенно поможет. Просто пока какое-то гадание на кофейной гуще, что там у вас происходит.

Аватар пользователя charOFF charOFF 9 марта в 15:19

Вам надо внимательно посмотреть вывод dpm формы внутри функции форм альтера, найти там поле, перед которым надо вставить кнопку. Оно может быть и не на верхнем уровне. Например, поле пароль в форме регистрации находится внутри контейнера 'account', т.е. в $form['account']['pass']. Если так, то надо вставлять 'changethis' не в $form, а в $form['account'].
По поводу весов - тоже надо смотреть. В той же форме регистрации, веса для элементов внутри $form['account'] по-умолчанию не заданы и рендерятся в порядке следования в массиве. В этом случае нужно массив $form['account'] перебирать и назначать всем элементам нужный вес. Тогда можно будет осмысленно вставить кнопку в нужное место.

Аватар пользователя maiskiykot maiskiykot 9 марта в 18:30

Да уж. Век живи - век лечись. Помогло. Но только пришлось сделать $form['account']['pass']['changethis']. И все равно или до полей с паролем встает или после. Между полями так и не дает вставить.

Аватар пользователя charOFF charOFF 10 марта в 11:35

maiskiykot wrote:
И все равно или до полей с паролем встает или после. Между полями так и не дает вставить.

Это потому что оба поля паролей на стадии форм альтера - это один элемент формы 'password_confirm', а разделяется на два он уже на следующих этапах.

В принципе, можно и между добавить. Но тогда кнопку надо добавлять в другом месте. В форм альтере можно для пароля прописать функции процесса, добавив к ним свою кастомную:

<?php
$form
['account']['pass']['#process'] = array(
      
'form_process_password_confirm',
      
'user_form_process_password_confirm',
      
'MYMODULE_process_password_confirm'
);
?>

А уже в функции MYMODULE_process_password_confirm($element) добавлять кнопку. Там в $element уже будут оба поля паролей.

Аватар пользователя maiskiykot maiskiykot 10 марта в 15:34

Да я уж смирился, что под полями пароля прилепилась кнопка. В принципе уместно. Немного оффтоп, но обнаружил явный глюк. При отправке пользователю ссылки на первый вход открывается форма, которая вообще не поймешь как сформирована. И главный глюк ее в том, что можно не вводить пароли. Т.е. забывчивый юзер отправит форму с пустыми паролями и друпал это запишет. Я не стал проверять результат а тут же сделал поля пароля проверяемыми. Как-то многовато правок стандартных процедур получается для одного проекта.