I'm having troubles with a FORM in Drupal 8, the idea is:
Chose a radio value from radio-estaciones to recharge radio-contaminantes, but, after the callback, the result I see is empty, but in replace command I use, I see it correcly
This is the code of buildForm
public function buildForm(array $form, \Drupal\Core\Form\FormStateInterface $form_state){
$arrRadioContaminantes = array();
$arrRadioContaminantes["0"] = t("ALL");
//My function to access DB
$result = \Drupal\map_data\Controller\Contaminante::list();
foreach ($result as $it){
$arrRadioContaminantes[$it["id_contaminante"]] = t($it["description"]);
}
$form['radio_contaminantes'] = array(
'#type' => 'radios',
'#options' => $arrRadioContaminantes,
'#ajax' => [
'callback' => '::seleccionContaminantes',
'disable-refocus' => true,
'event' => 'change',
'wrapper' => 'radios-estaciones',
'method' => 'replace'
]
);
$form['radio_estaciones'] = array(
'#type' => 'radios',
'#id' => 'radios-estaciones',
'#options' => ['-1'=>t("SELECT CONTAMINANTE FIRST")]
);
$form['actions']['#type'] = 'actions';
$form['actions']['submit'] = array(
'#type' => 'submit',
'#value' => $this->t('Submit'),
'#button_type' => 'primary',
);
$form_state->setCached(false);
$form_state->setRebuild(true);
return $form;
}
This is callback function:
public function seleccionContaminantes(array &$form, FormStateInterface $form_state){
if($form_state->getValue("radio_contaminantes") != 0){
$form['radio_estaciones']["0"] = t("All");
}
//My Database function
$resultado = \Drupal\montar_mapa\Controller\Estacion::list($form_state->getValue("radio_contaminantes"));
foreach ($resultado as $it){
$form['radio_estaciones'][$it["id"]] = t($it["name"]);
}
$ajaxResp = new AjaxResponse();
$ajaxResp->addCommand(new \Drupal\Core\Ajax\ReplaceCommand('radios-estaciones', \Drupal::service('renderer')->render($form['radio_estaciones'])));
return $ajaxResp;
}
I try returning $form['radio_estaciones'] with same results, and try DataCommand pasing new values, same result... I need help
After change type to 'select' works fine.
Drupal have this bug active
https://www.drupal.org/project/drupal/issues/2758631
Same situation with checkboxes
Related
I have added a file upload field to my node and I am editing the node form in a custom module as shown in below code .
There is an ajax based dependent drop-down field in the form.Upon selecting a single value the dependent drop-down loads fine.
But I get the following error when I select multiple values from the drop-down:
An illegal choice has been detected. Please contact the site
administrator
I get this particular error because of the file upload field.When I remove it , the form works absolutely fine.
I couldn't found any clues to solve this problem so far.
My code is Below:-
<?php
function my_module_form_alter(&$form, &$form_state, $form_id) {
global $user;
switch ($form_id) {
case 'my_node_node_form':
form_load_include($form_state, 'inc', 'node', 'node.pages');
$country_list = load_countries();
$selected_country = isset($form_state['values']['course_country']) ? $form_state['values']['course_country'] : key($country_list);
$form['course_country'] = array(
'#type' => 'select',
'#title' => t('Select Your Country'),
'#weight' => 11,
'#options' => $country_list,
'#default_value' => $selected_country,
'#ajax' => array(
'callback' => 'city_dropdown_callback',
'wrapper' => 'city_wrapper_list',
),
'#multiple' => TRUE,
'#required' => TRUE,
);
$form['course_country_region'] = array(
'#type' => 'select',
'#title' => t('Select Your City'),
'#weight' => 12,
'#prefix' => '<div id="city_wrapper_list">',
'#suffix' => '</div>',
'#options' => load_cities($selected_country),
'#multiple' => TRUE,
'#required' => TRUE,
);
unset($form['field_upload_resouces']);
break;
}
}
function city_dropdown_callback($form, $form_state) {
return $form['course_country_region'];
}
function load_countries(){
$sel_query = db_select('country', 'cd');
$sel_query->fields('cd');
$result = $sel_query->execute();
while ($data = $result->fetchAssoc()) {
$country_list[$data['id']] = $data['name'];
}
return $country_list;
}
function load_cities($country_id) {
$region_list = array('any' => 'Any');
$sel_query = db_select('city', 'cd');
$sel_query->fields('cd');
if(is_array($country_id)){
$sel_query->condition('cd.country_id', $country_id, 'IN');
}else{
$sel_query->condition('cd.country_id', $country_id);
}
$result = $sel_query->execute();
while ($data = $result->fetchAssoc()) {
$city_list[$data['id']] = $data['name'];
}
return $city_list;
}
I had similar issue and I solved by updating jquery.form.js to the latest version.
Please refer the link https://www.drupal.org/node/153774#comment-9202403 for more details.
I have a content type (budget), it is a custom content type
function budget_node_info() {
return array(
'budget' => array(
'base' => 'budget',
'name' => t('Budget'),
'description' => t('Represents individual budget.'),
'title_label' => t('Budget Name'),
'locked' => TRUE
)
);
}
also I have the form function
function budget_form($node, $form_state) {
drupal_add_library('system', 'ui.tabs');
drupal_add_library('budget', 'highcharts');
drupal_add_js(drupal_get_path('module', 'budget') . '/js/budget_base.js');
drupal_add_js(drupal_get_path('module', 'budget') . '/js/' . $node->type . '.js');
$form = node_content_form($node, $form_state);
$config = variable_get($node->type);
I want to show the edit form on the node view page (I want to show form from node/[nid]/edit to node/[nid])?
I tried next:
function budget_node_view($node, $view_mode, $langcode){
$node->content['edit-form'] = array(
'#markup' => render(drupal_get_form('budget_form', $node)),
'#weight' => 10,
);
}
also I tried
function budget_node_view($node, $view_mode, $langcode){
$node->content['edit-form'] = array(
'#markup' => render(budget_form($node, array())),
'#weight' => 10,
);
}
2nd version show form but without any js or css loaded.
What am I doing wrong?
I used function node_page_edit($node) and seems like it works
function wp_budget_node_view($node, $view_mode, $langcode){
module_load_include('inc', 'node', 'node.pages');
$node->content['edit-form'] = array(
'#markup' => render(node_page_edit($node)),
'#weight' => 10,
);
}
also for new (empty) form you should use node_add function function node_add($type
My custom module code:
<?php
function my_module_menu() {
$items = array();
$items['form-example'] = array(
'title' => 'My Module Form',
'description' => 'A form to mess around with.',
'page callback' => 'drupal_get_form',
'page arguments' => array('my_module_form'),
'access callback' => TRUE
);
return $items;
}
function my_module_form($form, &$form_state, $no_js_use = FALSE) {
$form['file'] = array(
'#type' => 'file',
'#title' => t('Image'),
'#description' => t('Upload an image'),
);
$form['menu'] = array(
'#markup' => '<b>Add More:</b>'
);
$form['#tree'] = TRUE;
$form['names_fieldset'] = array(
'#type' => 'fieldset',
'#title' => t('Add more images'),
'#prefix' => '<div id="names-fieldset-wrapper">',
'#suffix' => '</div>',
);
if (empty($form_state['num_names'])) {
$form_state['num_names'] = 1;
}
for ($i = 0; $i < $form_state['num_names']; $i++) {
$form['names_fieldset']['name'][$i][0]= array(
'#title' => t('Image'),
'#type' => 'file',
'#weight' => '5',
'#description' => t('Upload an image'),
);
}
$form['names_fieldset']['add_name'] = array(
'#type' => 'submit',
'#value' => t('Add one more'),
'#submit' => array('my_module_add_more_add_one'),
'#ajax' => array(
'callback' => 'my_module_add_more_callback',
'wrapper' => 'names-fieldset-wrapper',
),
);
if ($form_state['num_names'] > 1) {
$form['names_fieldset']['remove_name'] = array(
'#type' => 'submit',
'#value' => t('Remove one'),
'#submit' => array('my_module_add_more_remove_one'),
'#ajax' => array(
'callback' => 'my_module_add_more_callback',
'wrapper' => 'names-fieldset-wrapper',
),
);
}
$form['submit'] = array(
'#type' => 'submit',
'#value' => t('Submit'),
);
$form['#submit'][] = 'my_module_add_more_submit';
if ($no_js_use) {
if (!empty($form['names_fieldset']['remove_name']['#ajax'])) {
unset($form['names_fieldset']['remove_name']['#ajax']);
}
unset($form['names_fieldset']['add_name']['#ajax']);
}
return $form;
}
function my_module_add_more_callback($form, $form_state) {
return $form['names_fieldset'];
}
function my_module_add_more_add_one($form, &$form_state) {
$form_state['num_names']++;
$form_state['rebuild'] = TRUE;
//$form_state['no_redirect'] = TRUE;
}
function my_module_add_more_remove_one($form, &$form_state) {
if ($form_state['num_names'] > 1) {
$form_state['num_names']--;
}
$form_state['rebuild'] = TRUE;
}
function my_module_add_more_submit($form, &$form_state) {
$file = $form_state['values']['file']."<br \>";
$validators = array();
$file = file_save_upload('file', $validators, 'public://uploads');
print_r($file);
exit();
}
When i submit the form, i am trying to get the details of images, that are added through Add More option. But i am not able to get them. However i am only able to get the details of the first image (and able to upload it).
I want to know two things here:
How can i retrieve the details of the images that are added with Add More option (fieldset), and how can i upload them ?
When i browse and select an image in the fieldset, it is not retained in the form, after adding another image field. How to retain the selected images in fieldset ?
Look at this article -- http://evolvingweb.ca/story/poutine-maker-introduction-field-api-drupal-7-part-1 -- as it has some information on something missing in your code. $delta. $delta is the id assigned to values of fields, even if your field only has 1 item.
What do you see when you var_dump the file field you created? If you get all the information along with those added using 'Add one more' button, you can learn the correct structure of the values using: echo "<pre>"; print_R($form_state['values']); echo "</pre>":
There are a couple of issues with your code.
The first issue is that your submit function only deals with the first upload field which is indeed called "file". But does absolutely nothing to handle the other fields.
A second issue is that it will upload and save the first field every time you click on "Add one more" which will duplicate your upload. You would not experience this issue without AJAX, but if you want to add that, you will.
I would make the following changes:
Remove the $form['#tree'] = TRUE and add it to the fieldset instead. $form['names_fieldsets']['#tree'] = TRUE; after you declare the fieldset of course.
Change the way you declare the file fields in the fieldset (inside the for loop) to this:
for ($i = 0; $i < $form_state['num_names']; $i++) {
$form['names_fieldset'][$i]['name']= array(
'#title' => t('Image'),
'#type' => 'file',
'#weight' => '5',
'#description' => t('Upload an image'),
// We need this to know which file element this is.
// By default drupal would name all as files[names_fieldset]
'#name' => 'files[names_fieldset_' . $i . '_name]',
);
}
I would change the submit function like this (note that I assume you also do my above suggested changes):
function my_module_add_more_submit($form, &$form_state) {
if ($form_state['values']['op'] == 'Submit') {
$validators = array();
$files = array();
if (!empty($_FILES['files']['name']['file'])) {
$files[] = file_save_upload('file', $validators, file_default_scheme() . '://uploads');
}
foreach ($form_state['values']['names_fieldset'] as $name => $field) {
if ($name != 'add_name') {
$file_name = implode('_', $form['names_fieldset'][$name]['name']['#parents']);
if (!empty($_FILES['files']['name'][$file_name])) {
$files[] = file_save_upload($file_name, $validators, file_default_scheme() . '://uploads');
}
}
}
}
}
With this changes we set a form field name aware that's inside a tree. We only trigger uploads when the "Submit" button is clicked and only for form fields that actually had a file added to them. Also we upload using the default scheme and don't use always the public one.
Of course the code need some messages for the user to know how many files did upload, names, or any other deemed worthy info.
What I want to do is: I want to render a form on a page with a view. This view has a list of 'notes' (=CT Note). When you fill in the form, the note is stored, the form is cleared, and the new note is added to the list. All without page refreshes.
I create a module new_note, and addes this function:
function new_note_form($nodeid = NULL) {
ctools_include('ajax');
// drupal_add_js(drupal_get_path('module', 'custom_forms') . '/js/note_form.js');
//dpm($nodeid);
module_load_include('inc', 'node', 'node.pages');
$form = node_add('note');
$form['field_note_reference']['und']['#value'] = '2';
$form['field_note_reference']['und']['#validated'] = 'TRUE';
$form['field_note_reference']['#attributes']['class'][] = "hidden";
$form['submit'] = array(
'#type' => 'submit',
'#value' => 'Submit',
'#executes_submit_callback' => FALSE,
'#ajax' => array(
'callback' => 'ajax_note',
'wrapper' => 'status',
),
);
$output= drupal_render($form);
dpm($form);
print $output;
}
function ajax_note(&$form, &$form_state) {
return 'test';
}
I use this function in a display suite block field, which is rendered above the note list. So far so good.
The only problem is, that when I submit the form, the ajax is not called, and the normal submit is done.
Can anyone help me out
# Edit.
After what clive suggested I changed the code, and got the ajax working.
function new_notes_form($nodeid = NULL) {
global $user;
$node = (object) array(
'uid' => $user->uid,
'name' => (isset($user->name) ? $user->name : ''),
'type' => 'note',
'language' => LANGUAGE_NONE,
);
$form_state = array();
$form_state['build_info']['args'] = array($node);
form_load_include($form_state, 'inc', 'node', 'node.pages');
$form = drupal_build_form('note_node_form', $form_state);
$form['field_note_reference']['und']['#value'] = '2';
$form['field_note_reference']['#attributes']['class'][] = "hidden";
$form['submit'] = array(
'#type' => 'button',
'#value' => 'Submit',
'#limit_validation_errors' => array(),
'#ajax' => array(
'callback' => 'ajax_note_replace',
'wrapper' => 'status',
),
);
return $form;
}
function ajax_note_replace(&$form, &$form_state) {
dpm("test");
dpm($form);
$output = '<h1>' . t('Hello World') . '</h1>';
// $node = node_load('6');
// $output .= drupal_render(node_view($node, $style = 'teaser', $options = array()));
ctools_include('ajax');
$commands = array();
$commands[] = ajax_command_prepend(".view-content", $output);
print ajax_render($commands); // this function exits.
exit;
}
#Clive, can you help me out with the rest ? I want to save the node on callback (if valid?). In the ajax callback my node-id is null because it is not stored yet? how can I validate and save the node, otherwise set the not valid form items to red as normal.
It's likely to be because you're sidestepping Drupal's proper methods for creating forms so the AJAX preprocessing won't be performed. If you have a look at drupal_get_form() (the function used pretty much exclusively to prepare a form in Drupal) you'll see it in turn calls drupal_build_form() which is what you need to do:
function new_note_form($form, &$form_state, $nodeid = NULL) {
$form_state['build_info']['args'] = array('note');
$form = drupal_build_form('node_add', $form_state);
$form['submit'] = array(
'#type' => 'button',
'#value' => 'Submit',
'#limit_validation_errors' => array(),
'#ajax' => array(
'callback' => 'advanced_form_callback',
'wrapper' => 'status',
),
);
return $form;
}
echo render(drupal_get_form('new_note_form'));
I've changed the element from type submit to button because I find it works much better when you want to do some ajax processing, removed #executes_submit_callback, and added #limit_validation_errors which will stop the form from otherwise validating (I think that's what you were trying to do by setting #validated to TRUE but I might be wrong).
Hope that helps, it's untested but should give you a good place to start.
I am a beginner in the module development field and i am facing a problem.
I have created the .module file with the hook_menu function having following peice of code :-
$items['game/add_tournament/view_tournament']=array(
'title'=>'View Tournament',
'description'=>'Tournament View',
'page callback'=>'game_view_tournament_page',
'access callback' => 'user_access',
);
My Page callback is following :-
function game_view_tournament_page() {
$header_table_edit = array(
// first cell has the following text 'Title'
array('data' => t('Tournament Name')),
// second cell has the following text 'Link to edit'
array('data' => t('No of Weeks')),
array('data' => t('Start Date')),
array('data' => t('End Date')),
array('data' => t('Edit'))
);
$query = db_query
( "select tournament_id ,tournament_name ,tournament_no_of_weeks ,tournament_start_date ,tournament_end_date from {tournaments} ");
while ($data = db_fetch_object($query))
{
$rows_table_edit[] = array(
array('data' => l($data->tournament_name, 'game/add_tournament/view_tournament/' . $data -> tournament_id)),
array('data' => t($data->tournament_no_of_weeks)),
array('data' => t($data->tournament_start_date)),
array('data' => t($data->tournament_end_date)),
array('data' => l(t('Edit'),'game_tournament_edit/'.$data -> tournament_id.'/edit')) );
}
$caption_table_edit = t('Table for edit nodes');
return theme('table', $header_table_edit, $rows_table_edit);
}
Till this point the site works fine. Now comes the problem.
At this poinit i assume that another callback will be called when i hit edit button and that callback also should be registered in my hook_menu function.
Here i don't know if this method is being called back or not .Since everytime i hit edit button i get a Page not found error. The following is the callback
$items['game_week_edit/%game_abc/edit']=array(
'type' => MENU_LOCAL_TASK,
'access arguments' => array('access content'),
'page callback' => 'game_week_edit_page',
'page arguments' => array(1),
);
// The above code is in hook_menu function and the following code is outside hook_menu . Let me know if i am doing anything wrong.
function game_week_edit_page($abc_id){
return drupal_get_form('game_week_edit_form',$abc_id);
}
function game_week_edit_form( &$form_state, $abc_id) {
$form = array();
$options = array();
$sql = "SELECT game_week_id,tournament_id,start_time,open_time,close_time FROM {game_week} where game_week_id='$abc_id'";
$r = db_query($sql);
$sql_tournament = "SELECT tournament_name FROM {tournaments} ";
$r_tournament = db_query($sql_tournament);
while ($row = db_fetch_array($r_tournament)) {
$options[$row['tournament_name']] = $row['tournament_name'];
}
while ($row = db_fetch_object($r))
{
$form['tournament_name'] = array(
'#type' => 'select',
'#required'=>true,
'#title' => t('Select Tournament'),
'#options' => $options,
'#weight'=>1,
'#description' => t('<br>'),
);
$form['start_time'] = array(
'#type' => 'textfield',
'#required'=>true,
'#value'=>t($row->start_time),
'#title' => t('Enter Start Time'),
'#size'=>40,
'#maxlength'=>128,
'#weight'=>2,
'#description' => t('Please enter start time.'),
);
$form['open_time'] = array(
'#type' => 'textfield',
'#required'=>true,
'#value'=>t($row->open_time),
'#title' => t('Enter Tournament Start Time'),
'#size'=>40,
'#maxlength'=>128,
'#weight'=>3,
'#description' => t('Booking open time.'),
);
$form['close_time'] = array(
'#type' => 'textfield',
'#required'=>true,
'#value'=> t($row->close_time),
'#title' => t('Booking close time'),
'#size'=>40,
'#maxlength'=>128,
'#weight'=>4,
'#description' => t('Booking close time.'),
);
$form['submit'] = array(
'#type' => 'submit',
'#value' => t('Update Tournament'),
'#weight'=>5
);
}
return $form;
}
In hook_menu, try not naming your wildcard in the edit item. "%game_abc" is telling Drupal to call a function "game_abc_load" (that is, the name appended by "_load") and use the returned value as the first argument to your page callback "game_week_edit_page". If you don't have such a function, there will be problems.
In this case it looks like you just want to pass the integer id, in which case you can just use "%".