I am creating a module in which there is a dependency between combo boxes. There are three combo boxes: country, state, and district. If I select India in the country combo box, then the state combo box will contain all states of India, and the same in the case of district.
I have done this by using AJAX. It works properly in add form, but when I am going to update any one, the following error occurs:
An AJAX HTTP error occurred.
HTTP Result Code: 500
Debugging information follows.
Path: /drupal/?q=system/ajax
StatusText: Service unavailable (with message)
ResponseText: PDOException: SQLSTATE[42S22]: Column not found: 1054 Unknown column 'ajax' in 'where clause': SELECT district_name, country_id,state_id FROM {ajax_district} where id = ajax; Array
(
)
in edit_district_form() (line 291 of /home/mansmu/www/drupal/sites/default/modules/ajaxtest/ajaxtest.district.inc).
My code is:
////////////////////////////////////////////////////////
///////// FUNCTION FOR EDIT
////////////////////////////////////////////////////////
function edit_district_form($form, &$form_state) {
$request_url = request_uri();
// $request_id to get id of edit district.
$request_id = drupal_substr(strrchr($request_url, '/'), 1);
//// FOR country
$rows = array();
$result = db_query("SELECT id,country_name from {ajax_country} order by country_name");
while ($data = $result->fetchObject()) {
$id = $data->id;
$rows[$id] = $data->country_name;
}
//// FOR state
$state = array();
$result = db_query("SELECT id,state_name from {ajax_state} order by state_name");
while ($data = $result->fetchObject()) {
$id = $data->id;
$state[$id] = $data->state_name;
}
// $district_name varible to get name from database for a requested id.
$district_name = db_query("SELECT district_name, country_id,state_id FROM {ajax_district} where id = ".$request_id);
// Loop For show vehicle district name in text field to be update.
foreach ($district_name as $district) {*/
$form['values']['edit_country_name'] = array(
'#type' => 'select',
// '#default_value' => "{$district->country_id}",
'#required' => TRUE,
'#options' => $rows,
'#ajax' => array(
'effect' => 'fade',
'progress' => array('type' => 'none'),
'callback' => 'state_callback_edit',
'wrapper' => 'replace_edit_state',
),
);
$form['values']['edit_state_name'] = array(
'#type' => 'select',
// '#default_value' => "{$district->state_id}",
'#required' => TRUE,
'#options' => array(),
// The prefix/suffix provide the div that we're replacing, named by #ajax['wrapper'] above.
'#prefix' => '',
'#suffix' => '',
);
$form['values']['edit_district_name'] = array(
'#type' => 'textfield',
'#size' => 30,
//'#default_value' => "{$district->district_name}",
'#maxlength' => 80,
'#required' => TRUE,
);
}
$form['edit_district_submit'] = array(
'#type' => 'submit',
'#value' => t('Update'),
);
$form['actions']['cancel'] = array(
'#markup' => l(t('Cancel'), 'district'),
);
return $form;
}
////////////////////////////////////////////////////////
///////// FUNCTION FOR AJAX CALL BACK
////////////////////////////////////////////////////////
function state_callback_edit($form, &$form_state) {
// An AJAX request calls the form builder function for every change.
// We can change how we build the form based on $form_state.
if (!empty($form_state['values']['edit_country_name'])) {
$country_id = $form_state['values']['edit_country_name'];
$rows1 = array();
$result = db_query("SELECT id, state_name from {ajax_state} where country_id = $country_id order by state_name");
while ($data = $result->fetchObject()) {
$id = $data->id;
$rows1[$id] = $data->state_name;
}
$form['edit_state_name']['#options'] = $rows1;
}
return $form['values']['edit_state_name'];
}
Your line of code here:
$request_id = drupal_substr(strrchr($request_url, '/'), 1);
is returning the string 'ajax', making your third SQL statement look like this:
SELECT district_name, country_id,state_id FROM {ajax_district} where id = ajax;
Obviously 'ajax' is wrong there, I guess you want a value from the URL? You could use the arg() function to extract this so you don't need to run drupal_substr etc.
If your path is ajax/12 then arg(0) will return 'ajax', arg(1) will return 12 and so on.
Hope that helps
UPDATE
If you need to save the request ID in the form do something like this in your form function:
$form['request_id'] = array('#type' => 'value', '#value' => $request_id);
Then when you get into your ajax callback you can either get it from $form_state['values']['request_id'] or $form['request_id']['#value']
Related
Suppose I have items in database which is stored from an Excel file. All the items should be below the header of the months. I have also stored months from the file in the database. So, I want those months to be the header of those items and it's related records. In simple words, I want the header to be dynamic. This is what I have done.
I have tried many code scripts but nothing works. Like Laravel, Excel etc. Can anyone suggest me a good approach?
public function test(){
$data = Item::where('category_id',7)->get()->toArray();
$data2 = month::all();
$itemsArray[] = ['Category Id','Item Name','Created At','Updated At'];
foreach ($data as $value) {
// dd($value);
$itemsArray[] = array(
'Category Id' => $value['category_id'],
'Item Name' => $value['name'],
'Created At' => $value['created_at'],
'Updated At' => $value['updated_at'],
);
}
// Generate and return the spreadsheet
Excel::create('Items', function($excel) use ($itemsArray) {
// Set the spreadsheet title, creator, and description
$excel->setTitle('Items');
// Build the spreadsheet, passing in the items array
$excel->sheet('Items', function($sheet) use ($itemsArray) {
$cellRange = 'A1:D1';
// $spreadsheet->getActiveSheet()->getStyle('A1:D4')
// ->getAlignment()->setWrapText(true);
$sheet->getStyle($cellRange)->getFont()->setBold( true );
$sheet->getStyle($cellRange)->getFont()->setSize( '15' );
$sheet->setBorder($cellRange, 'thick' );
$sheet->getStyle($cellRange)->applyFromArray(array(
'fill' => array(
// 'type' => PHPExcel_Style_Fill::FILL_SOLID,
'color' => array('rgb' => 'A5D9FF')
)
));
$sheet->fromArray($itemsArray, null, 'A1', false, false);
});
$excel->setCreator('Laravel')->setCompany('Dev505');
$excel->setDescription('Items file');
})->download('xlsx');
}
I need help for getting the actual result.
Akhtar i suggest use to kindly install the Carbon package
https://carbon.nesbot.com/docs/
Try by updating the below code.
$data = Item::where('category_id',7)->get(); // removed toArray()
$data2 = month::all();
$itemsArray[] = ['Category Id','Item Name','Created At','Updated At'];
foreach ($data as $key=>$value) {
$itemsArray[] = array(
'month' => Carbon::now()->addMonth($key)->format('m-Y');
'Category Id' => $value['category_id'],
'Item Name' => $value['name'],
'Created At' => $value['created_at'],
'Updated At' => $value['updated_at'],
);
}
This is the actual code which I have used for excel file. I have solved my problem. Thanks and yeah I am posting this code, if anyone can get help from it.
public function export(){
$data = Category::all();
foreach ($data as $value) {
$value['items'] = Item::where('category_id',$value['id'])->get();
foreach ($value['items'] as $vl) {
$vl['record'] = Record::where('item_id',$vl['id'])->get();
}
}
$data2 = month::pluck('id','month');
foreach ($data2 as $key => $value) {
$m[] = $key;
}
array_unshift($m, 'Categories'); //Insert new element at the start of array
array_push($m, 'Total');
$itemsArray[] = $m;
foreach ($data as $value) {
$itemsArray[] = array(
$itemsArray[0][0] => $value['name'],
// $itemsArray[0][13] => 'Total',
);
foreach ($value['items'] as $val) {
$records_array = [];
$i = 0;
foreach ($val['record'] as $val5) {
$recordval = $val5['value'];
$records_array[$i] = $val5['value'];
$i++;
}
$itemsArray[] = array(
$itemsArray[0][0] => $val['name'],
$itemsArray[0][1] => $records_array[0],
$itemsArray[0][2] => $records_array[1],
$itemsArray[0][3] => $records_array[2],
$itemsArray[0][4] => $records_array[3],
$itemsArray[0][5] => $records_array[4],
$itemsArray[0][6] => $records_array[5],
$itemsArray[0][7] => $records_array[6],
$itemsArray[0][8] => $records_array[7],
$itemsArray[0][9] => $records_array[8],
$itemsArray[0][10] => $records_array[9],
$itemsArray[0][11] => $records_array[10],
$itemsArray[0][12] => $records_array[11],
// $itemsArray[0][13] => 'Total',
);
}
}
// Generate and return the spreadsheet
Excel::create('Items', function($excel) use ($itemsArray) {
// Set the spreadsheet title, creator, and description
$excel->setTitle('Items');
// Build the spreadsheet, passing in the items array
$excel->sheet('Items', function($sheet) use ($itemsArray) {
$cellRange = 'A1:M1';
$sheet->getStyle($cellRange)->getFont()->setBold( true );
$sheet->getStyle($cellRange)->getFont()->setSize( '12' );
$sheet->setBorder($cellRange, 'thin' );
$sheet->getStyle($cellRange)->applyFromArray(array(
'fill' => array(
// 'type' => PHPExcel_Style_Fill::FILL_SOLID,
'color' => array('rgb' => 'A5D9FF')
)
));
$sheet->fromArray($itemsArray, null, 'A1', false, false);
});
$excel->setCreator('Laravel')->setCompany('Dev505');
$excel->setDescription('Items file');
})->download('xlsx');
}
I am using the hook_form_FORM_ID_alter in Drupal 7 to create a custom form so that the user can enter and edit data which is then attached to a custom node type.
For a new node the default number of input boxes in a group is 10, this can then be added to in groups of 5. When the node is reloaded for editing the saved data is used to create the form with whatever number of inputs have been saved previously and also the ability to add more fields in the same manner as required.
I have managed to get both the initial version of the form and the editing version to work using the following code however when the 'add five' button is pressed and the AJAX called (in both cases), any values which have been entered without saving are removed.
<?php
/**
* Implements hook_form_FORM_ID_alter().
*/
function entries_form_form_entries_node_form_alter(&$form, &$form_state, $form_id) {
$node = $form['#node'];
// fieldset
$form["section"] = array(
'#type' => 'fieldset',
'#title'=> 'Section 1',
);
$form["section"]["termwrapper"] = array(
"#type" => 'container',
"#attributes" => array(
"id" => 'groupWrapper',
),
);
$form["section"]["termwrapper"]["terms"]["#tree"] = TRUE;
if(!isset($form_state['fired'])){
$form_state['terms'] = $node->entries_form['term'];
}
foreach ($form_state['terms'] as $key => $values) {
$form["section"]["termwrapper"]["terms"][$key] = array(
'#type' => 'textfield',
'#size' => 20,
'#attributes' => array(
'class' => array('left'),
),
'#value' => $values,
);
}
$form['section']['addFive_button'] = array(
'#type' => 'submit',
'#value' => t('+5'),
'#submit' => array('entries_form_add_five_submit'),
'#ajax' => array(
'callback' => 'entries_form_commands_add_callback',
'wrapper' => 'groupWrapper',
),
'#prefix' => "<div class='clear'></div>",
);
dpm($form_state);
}
function entries_form_commands_add_callback($form, $form_state) {
return $form["section"]["termwrapper"];
}
function entries_form_add_five_submit($form, &$form_state){
$form_state['rebuild'] = TRUE;
$form_state['fired'] = 1;
$values = $form_state['values'];
$form_state['terms'] = $values['terms'];
$numterms = count($values['terms']);
$addfivearray = array_fill($numterms,5,'');
$form_state['terms'] = array_merge($values['terms'],$addfivearray);
}
/**
* Implements hook_node_submit().
*/
function entries_form_node_submit($node, $form, &$form_state) {
$values = $form_state['values'];
$node->entries_form['term'] = $values['term'];
}
/**
* Implements hook_node_prepare().
*/
function entries_form_node_prepare($node) {
if (empty($node->entries_form)){
$node->entries_form['term'] = array_fill(0, 10, '');
}
}
/**
* Implements hook_node_load().
*/
function entries_form_node_load($nodes, $types) {
if($types[0] == 'entries'){
$result = db_query('SELECT * FROM {mytable} WHERE nid IN(:nids)', array(':nids' => array_keys($nodes)))->fetchAllAssoc('nid');
foreach ($nodes as &$node) {
$node->entries_form['term'] = json_decode($result[$node->nid]->term);
}
}
}
/**
* Implements hook_node_insert().
*/
function entries_form_node_insert($node) {
if (isset($node->entries_form)) {
db_insert('mytable')
->fields(array(
'nid' => $node->nid,
'term' => json_encode($node->entries_form['term']),
))
->execute();
}
}
How can I keep the values which have been typed in and retain the ajax functionality?
Any help or pointers much appreciated. This is my first dip into Drupal so I'm sure there is something which hopefully is quite obvious that I'm missing.
Ok, I think I finally have the answer.
Within the foreach that builds the form input boxes I had set '#value' => $values, when it seems that '#default_value' => $values, should have been set instead.
The updated section of the code that is now working for me is as follows
foreach ($form_state['terms'] as $key => $values) {
$form["section"]["termwrapper"]["terms"][$key] = array(
'#type' => 'textfield',
'#size' => 20,
'#attributes' => array(
'class' => array('left'),
),
'#default_value' => $values,
);
}
Seems to be as simple as that. Hope this helps someone else.
First time on stackoverflow so , i will try to be as clear as possible.
I'm using drupal 7 and views 3.
I needed to create a custom views filter that handle dates range. So i looked at example and tried to mimic the behavior and i get some trouble.
It seems that when i extend my own class from views_handler_filter , the query method is never invoked BUT if i extend my class from let's say views_handler_filter_string, it works oO...
I must forget something but i'm stuck here ...
Here is my code, if someone can take a look and advise me about what happend , i would be very grateful.
Thanks everyone !
Here is my .views.inc file :
<?php
class v3d_date_custom_filter extends views_handler_filter {
var $always_multiple = TRUE;
function value_form(&$form, &$form_state) {
//parent::value_form($form, $form_state);
$form['value']['v3d_date']['period'] = array(
'#type' => 'select',
'#title' => 'Period',
'#options' => array(
'7_days' => 'Last 7 days',
'yesterday' => 'Yesterday',
'today' => 'Today',
'custom' => 'Custom dates'),
'#default_value' => 'custom',
'#attributes' => array("onclick" => "period_click(this);"),
);
$form['value']['v3d_date']['start_date'] = array(
'#type' => 'date_popup',
'#date_format' => 'Y-m-d',
'#title' => 'Start date',
'#size' => 30);
$form['value']['v3d_date']['end_date'] = array(
'#type' => date_popup',
'#title' => 'End date',
'#date_format' => 'Y-m-d',
'#size' => 30);
}
function exposed_validate(&$form, &$form_state) {
if(is_null($form_state['values']['start_date']) &&
is_null($form_state['values']['start_date'])) {
return TRUE;
}
/*
* If we get array for start_date or end_date
* errors occured, but the date module will handle it.
*/
if(!is_string($form_state['values']['start_date']) ||
!is_string($form_state['values']['end_date'])) {
return TRUE;
}
/* Get day, month and year from start_date string */
if(!preg_match('/(\d+)-(\d+)-(\d+)/',
$form_state['values']['start_date'],
$start_date
)) {
return TRUE; }
/* Get day, month and year from end_date string */
if(!preg_match('/(\d+)-(\d+)-(\d+)/',
$form_state['values']['end_date'],
$end_date
)) {
return TRUE; }
/* Create timestamps and compare */
$start_date = mktime(0,0,0,$start_date[1],$start_date[2],$start_date[3]);
$end_date = mktime(0,0,0,$end_date[1],$end_date[2],$end_date[3]);
if($start_date >= $end_date) {
form_set_error('start_date','Start date must be anterior to end date.');
}
}
function query() {
die('fdsfds');
$this->ensure_my_table();
$field = "$this->table_alias.$this->real_field";
dsm($this);
}
}
?>
And my .module file
<?php
function custom_filters_views_api() {
return array(
'api'=>3,
'path' => drupal_get_path('module','custom_filters') . '/views',
);
}
?>
And part of my views_data that use my custom filter :
<?php
function voice_views_data() {
$data['v_tp_voice']['date_utc_agent'] = array(
'title' => t('date_utc_agent'),
'help' => 'date_utc_agent',
'field' => array('handler' => 'views_handler_field'),
'filter' => array('handler' => 'v3d_date_custom_filter'),
'sort' => array('handler' => 'views_handler_sort')
);
I am working on this same problem. My setup looks very much like yours, though I do call parent::value_form($form, $form_state) in my value_form function.
I found that in the value_form function, I had to have something like
$form['value'] = array(
'#type' => 'checkbox',
'#title' => "Filter by Date",
'#default_value' => $this->value,
);
in order to have my query() function called. Doing something like $form['value']['before'] = array( ...
didn't work.
Anyone know how to get a campaign to send to a segment? This code isn't working. It will send an email to all people in the campaign. It will not use the segment. (This is some more text so I can get it to pass the validation of SO.)
My code:
//get member list
$memberArray = $api->listMembers($inStockListId);
foreach ($memberArray['data'] as $member) {
$memberInfo = $api->listMemberInfo($inStockListId, $member['email']);
$_productId = $memberInfo['data'][0]['merges']['PRODUCTID'];
$productId='34';
if ($productId == $_productId) {
array_push($emailArray, $member['email']);
}
}
//create new segment for campaign
$listStaticSegmentId = $api->listStaticSegmentAdd($inStockListId, 'inStockStaticSegment');
//add members to segment
$val = $api->listStaticSegmentMembersAdd($inStockListId, $listStaticSegmentId, $emailArray);
$conditions = array();
$conditions[] = array(
'field' => 'email',
'op' => 'like',
'value' => '%'
);
$segment_options = array(
'match' => 'all',
'conditions' => $conditions
);
$type = 'regular';
$options = array(
'template_id' => $campaignTemplateId,
'list_id' => $inStockListId,
'subject' => 'In-Stock Notification',
'from_email' => 'from#email.com',
'from_name' => 'My From Name'
);
$content = array(
'html_main' => 'some pretty html content',
'html_sidecolumn' => 'this goes in a side column',
'html_header' => 'this gets placed in the header',
'html_footer' => 'the footer with an *|UNSUB|* message',
'text' => 'text content text content *|UNSUB|*'
);
$newCampaignId = $api->campaignCreate($type, $options, $content, $segment_options);
I figured it out. Essentially, here is the flow. If you want detailed code, send me a message and I'll be glad to help.
$api = new MCAPI($this->_apiKey);
$api->listMemberInfo($this->_listId, $member['email']);
$api->listUpdateMember($this->_listId, $member['email'], $mergeVars);
$api->listStaticSegmentDel($this->_listId, $segment['id']);
$api->listStaticSegmentAdd($this->_listId, $segmentName);
$api->listStaticSegmentMembersAdd($this->_listId, $segmentId, $emailArray);
$api->campaignCreate($type, $options, $content, $segment_options);
//$api->campaignSendTest($newCampaignId, array($member['email']));
$api->campaignSendNow($newCampaignId);
Note, this is done via the MailChimp PHP API.
I'm also using drupal-7 and create a module. A form in which there are 2 drop downs. On selection of car model (1st drop down) car variant (2nd drop down) value will change. It work perfectly when I am creating new one. But once I go to edit some value it shows me error.
===========================================================================
An AJAX HTTP error occurred.
HTTP Result Code: 500
Debugging information follows.
Path: /vehicle_ades/?q=system/ajax
StatusText: Service unavailable (with message)
ResponseText: PDOException: SQLSTATE[42S22]: Column not found: 1054 Unknown column 'ajax' in 'where clause':
SELECT heading,details,value_of_offer,exchange_offer,total_savings,car_model_id,car_variant_id FROM {va_offer} where id = ajax; Array ( )
===========================================================================
How do I pass car model id to ajax function
I'm working on drupal 7. Below is the code. What I have done is on selection of car model car variant will change and the data save in the table.
function add_offer_form($form, $formstate) {
$form['add_offer_new_car_model'] = array(
'#type' => 'select',
'#required' => TRUE,
'#options' => $car_model,
'#ajax' => array(
'effect' => 'fade',
'progress' => array('type' => 'none'),
'callback' => 'variant_callback',
'wrapper' => 'replace_variant',
),
);
// Combo box to select new car variant
$form['add_offer_new_car_variant'] = array(
'#type' => 'select',
'#options' => array(),
// The prefix/suffix provide the div that we're replacing, named by #ajax['wrapper'] above.
'#prefix' => '<div id="replace_variant">',
'#suffix' => '</div>',
);
// An AJAX request calls the form builder function for every change.
// We can change how we build the form based on $form_state.
if (!empty($formstate['values']['add_offer_new_car_model'])) {
$model_id = $formstate['values']['add_offer_new_car_model'];
$rows = array();
$result = db_query("SELECT id, variant_name from {va_car_variant} where car_model_id in ($model_id,1) order by variant_name");
while ($data = $result->fetchObject()) {
$id = $data->id;
$rows[$id] = $data->variant_name;
}
$form['add_offer_new_car_variant']['#options'] = $rows;
}
}
//////////////////////////////////////////////////////// ///////// FUNCTION FOR AJAX CALL BACK
function variant_callback($form, &$form_state) {
return $form['add_offer_new_car_variant'];
}