I've create a form like:
function create_custom_form($form, &$form_state) {
$form['#action'] = "#";
....
}
function create_custom_form_validate($form, &$form_state) {
....
}
function create_custom_form_submit($form, &$form_state) {
....
if(..)
drupal_goto('abc');
else
drupal_goto('xxx');
}
when i submit this form drupal before go to action and after read my function... how I can bypass the action-form and read only a _submit function?
Do not use drupal_goto as there may be more "submit" callbacks to execute. The drupal_goto function will interrupt these.
Instead, use the $form_state['redirect'] = ...
http://api.drupal.org/api/drupal/includes!form.inc/function/drupal_redirect_form/7
function create_custom_form_submit($form, &$form_state) {
....
if(..)
$form_state['redirect'] = 'abc';
else
$form_state['redirect'] = 'xxx';
}
As this function has the same form ID (create_custom_form) - with the word "_submit" appended then this function will be executed automatically and so there is no need to add any submit callbacks into the form.
If you want an additional function to execute on submit then you should do as Hamza has suggested, only your additional function will have a different name. e.g.
function create_custom_form($form, &$form_state) {
$form['#action'] = "#";
....
// Add any additional callbacks to call before any redirects happen
$form['#submit'][] = 'create_custom_form_additional_submit_callback';
$form['#submit'][] = ...
}
function create_custom_form_additional_submit_callback($form, &$form_state) {
// Do something before redirect
...
}
In the above example:
create_custom_form_additional_submit_callback
AND
create_custom_form_submit (because its got the same name with '_submit' appended)
will execute and only when they have both finished will the redirect be executed.
Related
function module_form_alter(&$form, $form_state, $form_id) {
if($form_id == "user_login"){
$form['#submit'][] = 'module_userlogin_callback';
}
}
function module_userlogin_callback($form, $form_state){
global $base_url;
$current_path = $base_url . '/' .'about';
$form_state['redirect']=$current_path;
}
Thing is, the original submit callback user_login_submit has already a $form_state['redirect'] to user profile page and i want to alter that and redirect to about page with out overriding the original submit callback function.is it possible?currently $form_state['redirect'] given by me is not working.how can i unset it and redirect to about page?
I had similar issue but I fixed it by writing my form_alter function in template.php, like this:
your_theme_form_alter(&$form, $form_state, $form_id) {
if ($form_id == 'user_login') {
$form['#submit'][] = 'your_theme_userlogin_callback';
}
}
function your_theme_userlogin_callback(&$form, &$form_state) {
$form_state['redirect'] = '$url';//your redirect url path
}
So I've built a small conditional to evaluate which button is pressed in my form (as there are 2). This works fine and fires off the correct method and writes the appropriate data to the DB, however my redirect is not working. It saves() to the DB and then simply stays on the page designated as the POST route.
I suspect the problem has something to do with my conditional and the use of $this.
Here is my check_submit method:
public function check_submit()
{
if(!is_null(Input::get('add_to_invoice'))){
$this->invoice_add_item();
} elseif(!is_null(Input::get('complete_invoice'))) {
$this->invoice_complete();
}
}
Here is one of the 2 methods which I am currently testing:
public function invoice_add_item()
{
$input = Request::all();
$invoice_items = new Expense;
$invoice_items->item_id = $input['item_id'];
$invoice_items->category_id = $input['category'];
$invoice_items->price = $input['price'];
$invoice_items->store_id = $input['store'];
if(Input::has('business_expense'))
{
$invoice_items->business_expense = 1;
}
else{
$invoice_items->business_expense = 0;
}
$invoice_items->save();
return redirect('/');
}
Perhaps there is a better way of handling this in my routes(web) file, but I'm not sure how to go about this.
You should add the return to the check_submit() method. Something like
public function check_submit()
{
if(!is_null(Input::get('add_to_invoice'))){
return $this->invoice_add_item();
} elseif(!is_null(Input::get('complete_invoice'))) {
return $this->invoice_complete();
}
}
Better yet, you should probably return a boolean on invoice_add_item() and based on that, redirect the user to the correct place (or with some session flash variable with an error message)
I creating a text box dynamically (based on user selection)using jquery ..is there any way to provide validation for that text box from zend form..?
Yes there is.
most credits go to jeremy kendall see http://www.jeremykendall.net/2009/01/19/dynamically-adding-elements-to-zend-form/
The way i solved it is by doing a jquery/ajax call to a action which adds get a form element something like:
$.ajax({
type : "POST",
url : "/<controller>/addfield/",
success : function(newElements) {
// Insert new element before the submit button
$("#productsNew-submit-element").before(newElements);
}
});
What this does is it call a action that generates a form element and returns the html which you can then add
public function addfieldAction()
{
//use $ajaxContext = $this->_helper->getHelper('AjaxContext'); in the init to make it return html via ajax
$element = new Zend_Form_Element_Text("extraElement_1");
$element->setBelongsTo("yourForm");
$element->setLabel('myElementName');
/*
set other stuff like decorators or so
*/
//now create the html
$elements .= $element->__toString();
$this->view->fields = $elements;
}
After that you will get a new element in your form via ajax
Now when you submit you have to do that again but then pre validation
first check if your form has extraElements if so add them again
fill the add element with the posted value
validate
public function saveAction()
{
function findFields($field) {
// return field names that include 'extraElement_'
if (strpos($field, 'extraElement_') !== false) {
return $field;
}
}
//set all stuff you need especially the form
if($this->getRequest()->isPost()) {
$postValues = $this->getRequest()->getPost();
//step 1
$extraFields = array_filter(array_keys(current($postValues)), 'findFields');
//add the element before validation
if(count($extraFields) !== 0) {
foreach(extraFields as $extraField) {
$this->addFields($postValues[$extraField]); <-- step 2 add the field(s)
}
}
//step 3 validate
if($this->_form->isValid($postValues)) {
//do post validation stuff
} else {
//show errors
}
}
}
Im carrying out some form validation with codeigniter using a custom validation callback.
$this->form_validation->set_rules('testPost', 'test', 'callback_myTest');
The callback runs in a model and works as expected if the return value is TRUE or FALSE. However the docs also say you can return a string of your choice.
For example if I have a date which is validated, but then in the same function the format of the date is changed how would I return and retrieve this new formatted value back in my controller?
Thanks for reading and appreiate the help.
I'm not entirely sure I got what you were asking, but here's an attempt.
You could define a function within the constructor that serves as the callback, and from within that function use your model. Something like this:
<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
class Controllername extends CI_Controller {
private $processedValue;
public function index()
{
$this->form_validation->set_rules('testpost','test','callback');
if ($this->form_validation->run()) {
//validation successful
echo $this->processedValue; //outputs the value returned by the model
} else {
//validation failed
}
}
private function callback($input)
{
$this->load->model('yourmodel');
$return = $this->yourmodel->doStuff($input);
//now you have the user's input in $input
// and the returned value in $return
//do some checks and return true/false
$this->processedValue = $return;
}
}
public function myTest($data){ // as the callback made by "callback_myTest"
// Do your stuff here
if(condition failed)
{
$this->form_validation->set_message('myTest', "Your string message");
return false;
}
else
{
return true;
}
}
Please try this one.
I looked at function _execute in file Form_validation of codeigniter. It sets var $_field_data to the result of callback gets(If the result is not boolean). There is another function "set_value". Use it with the parameter which is name of your field e.g. set_value('testPost') and see if you can get the result.
The way Tank_Auth does this in a controller is like so
$this->form_validation->set_rules('login', 'Login', 'trim|required|xss_clean');
if ($this->form_validation->run()) {
// validation ok
$this->form_validation->set_value('login')
}
Using the set_value method of form_validation is undocumented however I believe this is how they get the processed value of login after it has been trimmed and cleaned.
I don't really like the idea of having to setup a new variable to store this value directly from the custom validation function.
edit: sorry, misunderstood the question. Use a custom callback, perhaps. Or use the php $_POST collection (skipping codeigniter)...apologies haven't tested, but I hope someone can build on this...
eg:
function _is_startdate_first($str)
{
$str= do something to $str;
or
$_POST['myinput'} = do something to $str;
}
================
This is how I rename my custom callbacks:
$this->form_validation->set_message('_is_startdate_first', 'The start date must be first');
.....
Separately, here's the callback function:
function _is_startdate_first($str)
{
$startdate = new DateTime($this->input->post('startdate'), new DateTimeZone($this->tank_auth->timezone()));
$enddate = new DateTime($this->input->post('enddate'), new DateTimeZone($this->tank_auth->timezone()));
if ($startdate>$enddate) {
return false;
} else {
return true;
}
}
i am stuck in segments in codeigniter because it is new to me,
the problem with my login form.
i gave the url in action like action="blog/login/getLog" and
my login form shows in the url like blog/login
i know that in controller class i just create a function like with the name login but i created my controller file like this:
class Blog extends CI_Controller{
function __construct(){
parent::__construct();
}
// Now See
function _remap( $method ){
$this->load->view('header');
switch( $method ){
case 'about':
$this->load->view('about');
break;
case 'login':
$this->load->view('login');
break;
case 'services':
$this->load->view('service');
break;
}
$this->load->view('footer');
}
}//Close Class
but now don't know how to handle both segment like login and login/getLog .
EDIT: What happen exactly, when i click on the login button then i just see the login form according to _remap() and the url like blog/login and when i submitted the form and the url looking like blog/login/getLog, the login form still looking but i want to redirect it on success.. or want to detect the segment getLog if possible in the case 'login': if possible.
Thanks in advanced.
If you are sending through the URL, just use uri class:
$var = $this->uri->segment(3);
If you are sending in a form, send the variable through the form. Perhaps a hidden field?
$var = $this->input->post('var_name');
Edit: I'm not quite sure why you are using _remap for this w/o routing to another function (you are only trying to call a view file instead)
This is how I would expect to see the login form:
<?php echo form_open('blog/login');?>
<input type="hidden" name="getLog" value"true" />
<input type="submit" value="Login" />
</form>
Then in your Blog class i would rather put a function
public function login() {
if($this->input->post('getLog') === "true") {
//the form was submitted, let's check the login?
}
else {
//probably don't need an else, but form isn't submitted
}
}
Edit 2:
In case there are confusions and you actually want to use remap. You can do it like this to get the variables also.
function _remap( $method ) {
if ($method == ‘something’) {
$this->something();
}
else {
$this->somethingelse();
}
}
function something() {
$var1 = $this->uri->segment(3);
$var2 = $this->input->post('some_variable_name');
}
class Blog extends CI_Controller{
function __construct(){
parent::__construct();
}
// Now See
function _remap( $method ){
switch( $method ){
case 'about':
$this->about(); <---------- here method (Add header, content, footer inside respective functions)
break;
case 'login':
$this->login(); <------- here too
break;
case 'services':
$this->service(); <----- here too
break;
}
}
}//Close Class
what you have done here is, you overrided the default behavior of URI by _remap function.
The overridden function call (typically the second segment of the URI)
will be passed as a parameter to the _remap() function:
Simply, in most cases, the 2nd segment will become $method in the _remap function.
so your form action will become.
action = "<?php echo base_url('blog/login');?>"
add index.php if you haven't removed index.php from your url by htaccess.
EDIT:
As per your question,
but now don't know how to handle both segment like login and login/getLog .
this is how you deal.
Any extra segments after the method name are passed into _remap() as an optional second parameter.
public function _remap($method, $params = array())
{
// all other segments will be in $paramas array
}