I have a form with one field and a submit button with ajax submission option like following -
public function buildForm(array $form, FormStateInterface $form_state, $id = 0)
{
$form['fieldset']['message'] = array(
'#type' => 'textfield',
'#default_value' => "",
'#required' => true,
'#attributes' => array(
'placeholder' => t('write here'),
),
);
$form['actions']['submit'] = array(
'#type' => 'submit',
'#value' => $this->t('Send'),
'#attributes' => array(
'class' => array(
),
),
'#ajax' => [
'callback' => [$this, 'Ajaxsubmit'],
'event' => 'click']
);
return $form;
}
The ajax function is following -
public function Ajaxsubmit(array $form, FormStateInterface $form_state)
{
$user = \Drupal\user\Entity\User::load(\Drupal::currentUser()->id());
$db_values = [
"message" => $form_state->getValue("message"),
"date_create" => date("Y-m-d H:i:s"),
];
$save = DbStorage::Insert($db_values);
//$('#mychat_form input').val("");
//$form_state->setValue('content', NULL);
$response = new AjaxResponse();
if ($form_state->hasAnyErrors() || !$save) {
$response->addCommand(new AlertCommand('something wrong!'));
} else {
$message = DbStorage::Get(["id" => $save]);
$send_id = $message->send_id;
$build = [
'#theme' => "chat_view",
'#message' => $message,
'#sender' => $send_id,
'#current_user' => true
];
$ans_text = render($build);
$response->addCommand(new AppendCommand('#mychat', $ans_text));
}
return $response;
}
Here form data submission is working fine. But input data is not cleared after submission. I tried to clear it from my javascript using -
$('#my_form input').val("");
But the problem is my javascript file is called every 3 seconds and the form input is also cleared in every 3 seconds. this is problematic for users. Is there any other way to clear the form input after the ajax submission ? Can i do anything inside Ajaxsubmit function ?
You can use InvokeCommand for doing it.
For e.g: to clear an input value $('#my_form input').val(""); in ajax response
use Drupal\Core\Ajax\HtmlCommand;
use Drupal\Core\Ajax\InvokeCommand;
use Drupal\Core\Ajax\AppendCommand;
:
$form['fieldset']['message'] = array(
'#type' => 'textfield',
'#default_value' => "",
'#required' => true,
'#attributes' => array(
'placeholder' => t('write here'),
'class' => ['custom-class'],
),
);
In Ajax function
:
$build = [
'#theme' => "chat_view",
'#message' => $message,
'#sender' => $send_id,
'#current_user' => true
];
$response->addCommand(new AppendCommand('#mychat', $build));
$response->addCommand(new InvokeCommand('.custom-class', 'val', ['']));
Related
I tried to validate a simple form in zend framework 2 for days now.
I checked the documentation and a lot of posts considering this topic but I found no solution!
I have a very simple form:
class AlimentForm extends Form
{
public function __construct($name = null)
{
parent::__construct('aliment');
$this->add(array(
'required'=>true,
'name' => 'year',
'type' => 'Text',
'options' => array(
'label' => 'Jahr',
),
));
$this->add(array(
'required'=>true,
'name' => 'number',
'type' => 'Text',
'options' => array(
'label' => 'Number',
),
));
$this->add(array(
'name' => 'submit',
'type' => 'Submit',
'attributes' => array(
'value' => 'Go',
'id' => 'submitbutton',
),
));
}
}
I created a custom InputFilter:
namespace Application\Form;
use Zend\InputFilter\InputFilter;
class AlimentInputFilter extends InputFilter {
public function init()
{
$this->add([
'name' => AlimentForm::year,
'required' => true,
'validators' => array(
array(
'name' => 'Between',
'options' => array(
'min' => 1900,
'max' => 3000,
),
),
),
]);
}
}
and finally in my controller I try to validate the form
public function alimentAction(){
$form = new AlimentForm();
$form->setInputFilter(new AlimentInputFilter());
$request = $this->getRequest();
if ($request->isPost()) {
$form->setData($request->getPost());
if ($form->isValid()) {
$year = $form->get('year')->getValue();
$number = $form->get('number')->getValue();
return array('result' => array(
"msg" => "In the Year ".$year." you get ".$number." Points"
));
}
}
return array('form' => $form);
}
It can't be that difficult, but from all those different ways to validate a form I found in the net, I'm a bit confused...
What am I missing?
Greetings and thanks in advance
U.H.
Ok, I solved the problem.
I created a Model for the aliment Form that has a year and a number attribute
and I defined an input filter within that model:
use Zend\InputFilter\InputFilter;
use Zend\InputFilter\InputFilterAwareInterface;
use Zend\InputFilter\InputFilterInterface;
class Aliment implements InputFilterAwareInterface
{
public $year;
public $number;
public function exchangeArray($data){
$this->year = (!empty($data['year']))?$data['year']:null;
$this->number = (!empty($data['number']))?$data['number']:null;
}
public function setInputFilter(InputFilterInterface $inputFilter)
{
throw new \Exception("Not used");
}
public function getInputFilter()
{
if (!$this->inputFilter) {
$inputFilter = new InputFilter();
$inputFilter->add(array(
'name' => 'year',
'required' => true,
'filters' => array(
array('name' => 'StripTags'),
array('name' => 'StringTrim'),
),
'validators' => array(
array(
'name' => 'Between',
'options' => array(
'min' => 1900,
'max' => 3000
)
)
),
));
$inputFilter->add(array(
'name' => 'number',
'required' => true,
'filters' => array(
array('name' => 'StripTags'),
array('name' => 'StringTrim'),
),
'validators' => array(
array(
'name' => 'Between',
'options' => array(
'min' => 1,
'max' => 10
)
)
),
));
$this->inputFilter = $inputFilter;
}
return $this->inputFilter;
}
}
In the action method of the controller I was able to set the InputFilter of the model to the form and voila! It worked!
public function alimentAction(){
$form = new AlimentForm();
$request = $this->getRequest();
if ($request->isPost()) {
$aliment = new \Application\Model\Aliment;
$form->setInputFilter($aliment->getInputFilter());
$form->setData($request->getPost());
if ($form->isValid()) {
$aliment->exchangeArray($form->getData());
$year = $form->get('year')->getValue();
return array(
'result' => array(
//your result
)
);
}
}
return array('form' => $form);
}
The form is correctly validated now and returns the corresponding error messages.
I hope, it help somebody whos got similar problems with validating!
I have a custom form that creates a new user and fills in a number of custom fields for that user. One of these fields is a custom image (not the system avatar image).
I can get the image uploaded to the server through the form, but can't get it into the appropriate field. Here is my (custom module) code so-far.
function newacc_freebusiness_form($form, &$form_state) {
$form['bussimage'] = array(
'#title' => t('Upload an image that shows off your business.'),
'#type' => 'managed_file',
'#description' => t('Max size of 3Mb and filetype of jpg jpeg or png'),
'#upload_location' => 'public://bussimages/',
'#upload_validators' => array(
'file_validate_extensions' => array('png jpg jpeg'),
'file_validate_size' => array(3*1024*1024),
),
'#required' => TRUE,
);
$form['submit'] = array(
'#type' => 'submit',
'#value' => 'Submit',
);
$form['#validate'][] = 'newacc_freebusiness_validate';
return $form;
}
function newacc_freebusiness_validate($form, &$form_state) {
$bussimage = $form_state['values']['bussimage'];
$file = file_load($bussimage);
$bussimage = image_load($file -> uri);
image_save($bussimage);
$bussimage = image_load($file -> uri);
$edit = array(
'name' => 'name',
'mail' => 'mail#mail.com',
'status' => 0,
'language' => 'en',
'init' => 'mail#mail.com',
'roles' => array(8 => 'Promoter'),
'field_business_image' => array(
'und' => array(
0 => array(
'value' => $bussimage,
),
),
),
);
user_save(NULL, $edit);
}
This is throwing the error message:
Notice: Undefined index: fid in file_field_presave() (line 219 of /var/www/drupal_site/modules/file/file.field.inc).
I have tried so many tricks now and googled so long that I can't even explain what I have and haven't tried anymore!
Any help please.
OK - solved this. The clue was in the error message and the solution was very simple! Here is the code:
function newacc_freebusiness_form($form, &$form_state) {
$form['bussimage'] = array(
'#title' => t('Upload an image that shows off your business.'),
'#type' => 'managed_file',
'#description' => t('Max size of 3Mb and filetype of jpg jpeg or png'),
'#upload_location' => 'public://bussimages/',
'#upload_validators' => array(
'file_validate_extensions' => array('png jpg jpeg'),
'file_validate_size' => array(3*1024*1024),
),
'#required' => TRUE,
);
$form['submit'] = array(
'#type' => 'submit',
'#value' => 'Submit',
);
$form['#validate'][] = 'newacc_freebusiness_validate';
return $form;
}
function newacc_freebusiness_validate($form, &$form_state) {
$bussimage = $form_state['values']['bussimage'];
$file = file_load($bussimage);
$edit = array(
'name' => 'name',
'mail' => 'mail#mail.com',
'status' => 0,
'language' => 'en',
'init' => 'mail#mail.com',
'roles' => array(8 => 'Promoter'),
'field_business_image' => array(
'und' => array(
0 => array(
'fid' => $file -> fid,
),
),
),
);
user_save(NULL, $edit);
}
All Drupal was looking for was the file fid in the array. Don't know why I initially assumed it had to be more complicated than this.
I'm trying to working with the Uploader Plugin to create a structure where a User Model can upload it's avatar with the Avatar Model, I've read the instructions several times but when I try to $this->Uploader->upload('Avatar.filename') I get no validation errors but the upload method fails.
Here is how I've written the User Model
<?php
class User extends AppModel {
public $name = 'User';
public $hasOne = array(
'Profile' => array(
'className' => 'Profile',
'conditions' => '',
'dependent' => true,
'foreignKey' => 'user_id',
'associatedKey' => 'user_id'
),
'Avatar' => array (
'className' => 'Avatar',
'foreignKey' => 'user_id',
'dependent' => true
)
);
public $validate = array(...);
// other stuff not relevant here...
?>
Here is the Avatar Model
<?php
class Avatar extends AppModel {
public $name = 'Avatar';
public $actsAs = array (
'Uploader.Attachment' => array (
'Avatar.filename' => array(
'name' => 'setNameAsImgId', // Name of the function to use to format filenames
'baseDir' => '', // See UploaderComponent::$baseDir
'uploadDir' => 'files/avatars/', // See UploaderComponent::$uploadDir
'dbColumn' => 'filename', // The database column name to save the path to
'importFrom' => '', // Path or URL to import file
'defaultPath' => '', // Default file path if no upload present
'maxNameLength' => 500, // Max file name length
'overwrite' => true, // Overwrite file with same name if it exists
'stopSave' => true, // Stop the model save() if upload fails
'allowEmpty' => true, // Allow an empty file upload to continue
'transforms' => array (
array('method' => 'resize', 'width' => 128, 'height' => 128, 'dbColumn' => 'name')
) // What transformations to do on images: scale, resize, ete
)
),
'Uploader.FileValidation' => array (
'Avatar.filename' => array (
'maxWidth' => array (
'value' => 512,
'error' => 'maxWidth error'
),
'maxHeight' => array (
'value' => 512,
'error' => 'maxWidth error'
),
'extension' => array (
'value' => array('gif', 'jpg', 'png', 'jpeg'),
'error' => 'extension error'
),
'filesize' => array (
'value' => 5242880,
'error' => 'filesize error'
)
)
)
);
public $belongsTo = array(
'User' => array(
'className' => 'User',
'foreignKey' => 'user_id',
'conditions' => '',
'order' => ''
)
);
public function setNameAsImgId ($name, $field, $file) {
/**
* Format the filename a specific way before uploading and attaching.
*
* #access public
* #param string $name - The current filename without extension
* #param string $field - The form field name
* #param array $file - The $_FILES data
* #return string
*/
// devo ricavare l'id dell'immagine appena creata per rinominare il file
return $name;
}
}
?>
This is the UsersController for edit method
<?php
App::uses('CakeEmail','Network/Email');
CakePlugin::load('Uploader');
App::import('Vendor', 'Uploader.Uploader');
class UsersController extends AppController {
public $name = 'Users';
public function edit ($id) {
$this->User->id = $id;
if (!$this->User->exists()) {
throw new NotFoundException ('Nessuna corrispondenza trovata per questo utente');
}
if (!$id) {
$this->set('flash_element','error');
$this->Session->setFlash ('Utente non valido');
}
$this->User->recursive = 1;
$this->set('user', $this->User->read());
if ($this->request->is('post')) {
$this->User->id = $this->request->data['User']['id'];
if (!$this->User->exists()) {
$this->set('flash_element','warning');
$this->Session->setFlash('Nessun utente trovato con questa corrispondenza');
}
if ($this->User->save($this->request->data)) {
$this->request->data['Profile']['user_id'] = $this->User->id;
$conditions = array(
'conditions' => array(
'Profile.id' => $this->request->data['Profile']['id']
)
);
if ($this->User->Profile->save($this->request->data, $conditions)) {
if (!empty($this->request->data['Avatar']['filename'])) {
$this->request->data['Avatar']['user_id'] = $this->User->id;
if ($this->User->Avatar->save($this->request->data)) {
$avatar = $this->User->Avatar->find('first', array(
'conditions' => array('Avatar.user_id' => $this->User->id)
));
$ext = Uploader::ext($this->request->data['Avatar']['filename']);
$filename = $avatar['Avatar']['id'].'.'.$ext;
if ($this->User->Avatar->save('Avatar.filename')) {
$this->set('flash_element','done');
$this->Session->setFlash('Avatar changed successfully');
debug('saved successfully');
} else {
debug('not saved');
$this->set('flash_element','warning');
$this->Session->setFlash('Avatar not saved on the server');
}
} else {
$this->Session->write('flash_element','error');
$this->Session->setFlash('Avatar data not saved on the server');
$this->redirect(array('action'=>'index'));
}
} else {
$this->Session->write('flash_element','done');
$this->Session->setFlash('Data successfully saved, avatar not changed');
$this->redirect(array('action'=>'index'));
}
} else {
$this->set('flash_element','error');
$this->Session->setFlash('Error on saving Profile data to the server');
}
} else {
$this->Session->write('flash_element','error');
$this->Session->setFlash('Error on saving User data to the server');
$this->redirect(array('action'=>'index'));
}
}
}
}
?>
And in the view file I have this
<?php
echo $this->Form->create('User', array ('class' => 'form'));
echo $this->Form->input('User.id', array ('type'=>'hidden', 'value'=> $user['User']['id'],'label'=> false, 'id' => 'id'));
echo $this->Form->input('User.username', array ('label'=> false, 'value' => $user['User']['username'], 'id' => 'username', 'after' => '<div class="message">Message for username field'));
echo $this->Form->input('User.email', array ('label'=> false, 'value' => $user['User']['email'], 'id' => 'email', 'after' => '<div class="message">Message for email field</div>'));
echo $this->Form->input('UserOptions.id', array ('type'=>'hidden', 'value'=> $user['UserOptions']['id'],'label'=> false, 'id' => 'UserOptions.id'));
$attributes = array ('value' => $user['UserOptions']['avatar_type'], 'empty' => false);
$options = array('0' => 'This site', '1' => 'Gravatar');
echo $this->Form->select('UserOptions.avatar_type', $options, $attributes);
/* avatar code */
echo $this->Form->input('Avatar.id', array ('type'=>'hidden', 'value'=> $user['Avatar']['id'],'label'=> false, 'id' => 'Avatar.id'));
echo $this->Form->input('Avatar.filename', array('type' => 'file'));
/* end avatar code */
echo $this->Form->input('Profile.city', array ('label'=> false, 'value' => defaultValue ('City', $user['Profile']['city']), 'id' => 'city', 'after' => '<div class="message">Message for city field</div>'));
echo $this->Form->input('Profile.country', array ('label'=> false, 'value' => defaultValue('',$user['Profile']['country']), 'id' => 'country', 'after' => '<div class="message">Message for country field</div>'));
echo $this->Form->input('Profile.url', array ('label'=> false, 'value' => defaultValue('http://', $user['Profile']['url']), 'id' => 'url', 'after' => '<div class="message">Message for url field</div>'));
echo $this->Form->input('Profile.description', array ('label'=> false, 'value' => defaultValue('Description',$user['Profile']['description']), 'id' => 'description', 'after' => '<div class="message">Message for description field</div>'));
echo $this->Form->submit('Modifica', array('id'=>'edit'));
echo $this->Form->end();
?>
In the Controller, every part of the data is saved until I reach $this->Uploader->upload('Avatar.filename', array('overwrite' => true, 'name' => $filename)) where I get a generic error.
This Plugin seems to be the best way to do it without write tons of code, but I'm not sure how to use it.
I'm not sure what's wrong with the code, can You help me to solve the problem?
I've found the problems, I forgot two things:
In the view page I've forgot 'type' => 'file'
<?php
echo $this->Form->create('User', array ('class' => 'form', 'type' => 'file'));
?>
I was used to work with 1.3 version so the app/Config/bootstrap.php configuration was missing:
<?php
CakePlugin::load('Uploader');
?>
Now it works!
I am trying to make dynamic 3 dropdown(DD) by #ajax property of drupal 7..
1st DD contains country list(coming from db)
2nd DD contains states list(coming from db)
3re DD contains city list(coming from db)
problem is as i choose country ..my states DD show states accordingly..by how to trigger my states DD so that my city DD also got updated at the same time my state updated..I have to click on states table only then my cities DD changes..
---MY CODE IN FORM_ALTER IS THIS---
$options_first = iripple_classifieds_country_list();
$selected = isset($form_state['values']['country_by_alter']) ? $form_state['values']['country_by_alter']: key($options_first);
$options_first = iripple_classifieds_country_list();
$form['country_by_alter'] = array(
'#type' => 'select',
'#title' => t('Country'),
'#validated' => TRUE,
'#options' => $options_first,
'#weight' => 5,
//'#disabled' =>TRUE,
'#ajax' => array(
'callback' => 'iripple_classifieds_country_callback',
'wrapper' => 'statereplace',
'effect' => 'fade',
// 'event' => 'onload'
),
'#attributes' => array(
// 'onload' => "jQuery('#edit-country-by-alter').trigger('click')"
)
);
$options_second = iripple_classifieds_state_list();
$selected_state = isset($form_state['values']['state_by_alter']) ? $form_state['values']['state_by_alter']: key($options_second);
$form['state_by_alter'] = array (
'#type' => 'select',
'#title' => t('State'),
'#options' => iripple_classifieds_selected_states($selected),
'#default_value' => isset($form_state['values']['state_by_alter']) ? $form_state['values']['state_by_alter']:'',
'#weight' => 7,
'#validated' => TRUE,
'#prefix' => '<div id="statereplace">',
'#suffix' => '</div>',
'#ajax' => array(
'callback' => 'iripple_classifieds_state_callback',
'wrapper' => 'cityreplace',
'event' => 'change'
)
);
$form['city_by_alter'] = array(
'#type' => 'select',
'#title' => t('City'),
'#options' => iripple_classifieds_selected_cities($selected_state),
'#default_value' => isset($form_state['values']['city_by_alter']) ? $form_state['values']['city_by_alter']:'',
'#weight' => 8,
'#validated' => TRUE,
'#prefix' => '<div id="cityreplace">',
'#suffix' => '</div>',
);
From what I have tried in the past, unless you aren't using the field module, the Hierarchial Select module with either your custom module based off the included hs_smallhierarchy or the hs_taxonomy modules/select menus would work for your three level select element.
The hs_taxonomy module has the database calls you would need, otherwise you can just pass the information and use the former. I've search a lot of different sites and this is something I've tried to accomplish for some time. Looking at their code would show you the Javascript you would have to use and process for the second and third select items because as you stated, unless it isn't stated one page load you will run into problems.
I've gotten a 6 Level Ebay Category to change the options correctly, but it won't update $form_state after a certain level.
function ajax_pra_menu() { $items['ajax_pra'] = array(enter code here
'title' => 'ajax Practice',
'page callback' => 'drupal_get_form',
'page arguments' => array('ajax_pra_dependent_dropdown'),
'access callback' => TRUE,enter code here` );
return $items;
}
function ajax_pra_dependent_dropdown($form, &$form_state) { $options_first = _ajax_pra_get_first_dropdown_options();
$options_two = _ajax_pra_get_second_dropdown_options();
$selected = isset($form_state['values']['dropdown_first']) ? $form_state['values']['dropdown_first'] : key($options_first);
$select_two = isset($form_state['values']['dropdown_second']) ? $form_state['values']['dropdown_second'] : key($options_two);
$form['dropdown_first'] = array(
'#title' => 'Item',
'#type' => 'select',
'#options' => $options_first,
'#default_value' => $selected,
'#ajax' => array(
'callback' => 'ajax_pra_dependent_dropdown_callback',
'wrapper' => 'dropdown-second-replace'
),
);
$form['dropdown_second'] = array(
'#title' => $options_first[$selected] . ' ' . t('type'),
'#type' => 'select',
'#prefix' => '<div id="dropdown-second-replace">',
'#suffix' => '</div>',
'#options' => _ajax_pra_get_second_dropdown_options($selected),
'#default_value' => isset($form_state['values']['dropdown_second']) ? $form_state['values']['dropdown_second'] : '',
'#ajax' => array(
'callback' => 'ajax_pra_two_dependent_dropdown_callback',
'wrapper' => 'dropdown-third-replace',
),
);
$form['dropdown_third'] = array(
'#title' => $options_two[$select_two] . ' ' . t('third'),
'#type' => 'select',
'#prefix' => '<div id="dropdown-third-replace">',
'#suffix' => '</div>',
'#options' => _ajax_pra_get_third_dropdown_options($select_two),
'#default_value' => isset($form_state['values']['dropdown_third']) ? $form_state['values']['dropdown_third'] : '',
);
$form['submit'] = array(
'#type' => 'submit',
'#value' => t('save'),
);
}
function ajax_pra_dependent_dropdown_callback($form,$form_state)
{
return $form['dropdown_second'];
}
function ajax_pra_two_dependent_dropdown_callback($form,$form_state)
{
return $form['dropdown_third'];
}
function _ajax_pra_get_first_dropdown_options()
{
return drupal_map_assoc(
array(
t('Car'),
t('Bike'),
t('Mobile'),
)
);
}
function _ajax_pra_get_second_dropdown_options($key = ' ')
{
$options = array(
t('Car') => drupal_map_assoc(
array(
t('bmw'),
t('audi'),
)
),
t('Bike') => drupal_map_assoc(
array(
t('honda'),
t('suzuki'),
)
),
t('Mobile') => drupal_map_assoc(
array(
t('nokia'),
t('micro'),
)
),
);
if (isset($options[$key]))
{
return $options[$key];
}
else{
return array();
}
}
function _ajax_pra_get_third_dropdown_options($key = '')
{
$options = array(
t('bmw') => drupal_map_assoc(
array(
t('bmw x3'),
t('bmw x6'),
)
),
t('honda') => drupal_map_assoc(
array(
t('city'),
t('accord'),
)
),
);
if(isset($options[$key]))
{
return $options[$key];
}
else
{
return array();
}
}
I am trying to make a full cycle form with parameters and response page. Form is working OK, but response page is coming up black. Anyone have a suggestion or model example.
function module99_menu(){
$items = array();
// inital form
$items['module-99'] = array(
'title' => t('Export'), // Page title
'page callback' => 'fn_module99', // function to call when this page is called
'access arguments' => array('access content'), // An array of arguments to pass to the access callback function.
'description' => t('Export'),
'type' => MENU_CALLBACK,
);
// response page
$items['my_module-99-response/%/%'] = array(
'title' => t('Response Page'), // Page title
'page callback' => 'fn_module99_response', // function to call when this page is called
'page arguments' => array(0,1), // pass with arg(0) and arg(1)
'access arguments' => array('access content'),
'description' => t('Export - response form'),
'access callback' => TRUE,
'type' => MENU_CALLBACK,
);
function fn_module99() {
return drupal_get_form('module99_my_form');
}
function module99_my_form_validate($form, &$form_state) {
// do some validation
}
function module99_my_form_submit($form, &$form_state) {
// do some stuff
drupal_set_message(t('The form has been submitted.'));
$parms = "p1=" . "A" . "&p2=" . "B" ;
$form_state['redirect'] = array('my_module-99-response', $parms);
}
function fn_module99_response($parm1,$parm2) {
$output = $parm1 . $parm2;
return $output;
}
function module99_my_form($form_state){
$form = array();
$form['email'] = array(
'#type' => 'textfield',
'#title' => t('E-mail address') ,
'#size' => 64,
'#maxlength' => 64,
'#required' => TRUE,
);
$form['submit'] = array(
'#type' => 'submit',
'#value' => t('Save'),
);
return $form;
}
You should change the redirect a bit:
$form_state['redirect'] = array("my_module-99-response/$param_a/$param_b");
Also in your hook_menu you want to change the page arguments:
$items['my_module-99-response/%/%'] = array(
'page arguments' => array(1,2),
);
This will match the two % in your url, as 0 is 'my_module-99-response'.
I don't know if it will help, but the standard method is to use drupal_get_form on the hook menu with the form id of the form as a parameter. I'm not sure what you are trying to do with the arguments?
$items['my_module-99-response/'] = array(
'title' => t('Response Page'), // Page title
'page callback' => 'drupal_get_form',
'page arguments' => array('fn_module99_response'),
'access arguments' => array('access content'),
'description' => t('Export - response form'),
'access callback' => TRUE,
'type' => MENU_CALLBACK,
);
You should also specify a submit handler in the form using the '#submit' property (make sure you pass an array). Do validation in the same way while you are at it.
function module99_my_form($form_state){
$form = array();
$form['email'] = array(
'#type' => 'textfield',
'#title' => t('E-mail address') ,
'#size' => 64,
'#maxlength' => 64,
'#required' => TRUE,
);
$form['submit'] = array(
'#type' => 'submit',
'#value' => t('Save'),
);
$form['#submit'] = array('module99_my_form_submit') ;
$form['#validate'] = array('module99_my_form_validate') ;
return $form;
}
$form_state['redirect'] = array("my_module-99-response/$param_a/$param_b");
this works great except drupal mangles the slashes with encoding