Welcome Guest, Not a member yet? Register   Sign In
Multidimensional form arrays in Code Igniter with form_input and set_value
#1

[eluser]Ninjabear[/eluser]
Hi. I've been playing around with CI for a good while but have come across a serious problem with multidimensional arrays with forms. My application contains several blocks of code, each containing a name, url and description (textarea). First time the form is run I present one group of fields. If the user hits "add" they get another set. When the form is submitted it get validated and if something is wrong I need CI to validate the fields and place the info back in if there's a validation error, nothing weird there.

But the problem is that when the form is presented a second time I get "Array" in the text box. I've tried using:

form_input("name_field[]",set_value("name_field[]"));
form_input("name_field[index]",set_value("name_field[index]"));
<input type="text" name="name_field[]" value="<?=set_value("name_field[]")?>" />

Have read the following docs:

http://ellislab.com/codeigniter/user-gui...ysasfields
http://ellislab.com/codeigniter/user-gui...elper.html

My Controller in controllers/add/fixes
Code:
function Fixes()
    {
        
        $this->form_validation->set_error_delimiters('<p class="error">', '</p>');
        
        $this->form_validation->set_rules('name_field[]','Name of fix','trim|required|min_length[5]|max_length[100]');
        $this->form_validation->set_rules('desc_field[]','Description of fix','trim|required|min_length[10]|max_length[1000]');
        $this->form_validation->set_rules('url_field[]','URLs','trim|required|callback__Check_URL_Format');
        $this->form_validation->set_rules('num','','trim|required|num');
        
        if($this->form_validation->run())
        {
            
        }
        
        
            echo "post ".$this->input->post('num');
            
            if($this->input->post('num'))//Num = number of fixes so far.
                $options->num = $this->input->post('num');
            else
                $options->num=1;
            
            echo "skdjksjf ".$options->num;
            $this->load->view('add/step2',$options);
    }



My form in views/step2
Code:
&lt;?=form_open(base_url().'add/fixes');?&gt;
      
                <fieldset>
          <legend><h2>Add Fixes</h2></legend>
            
          &lt;? for($i=0;$i<$num;$i++): ?&gt;
          
          <div class="duplicates duplicate_&lt;?=$i?&gt;">
              <h4>Fix #&lt;?=$i?&gt;</h4>
            <div class="form_row">
              <div class="form_field">
                <label for="name_field">Name of Fix</label>
              </div>
              <div class="form_field">
                &lt;?
                //form_input("name_field[]",set_value("name_field[]"));
                                ?&gt;
                &lt;input type="text" name="name_field[]" value="&lt;?=set_value("name_field[($i+1)]")?&gt;" /&gt;
                &lt;?=form_error("name_field[($i+1)]");?&gt;
              </div>
            </div>
  
            <div class="form_row">
              <div class="form_field">
                <label for="name_field">External links (URLs) to fixes (One link on each line.).</label>
              </div>
              <div class="form_field">
                &lt;?=form_textarea('url_field[]',set_value('url_field[]',"http://"),'class="content"');?&gt;
                &lt;?=form_error('url_field[]');?&gt;
              </div>
            </div>
            
            <div class="form_row">
              <div class="form_field">
                <label for="desc_field">Describe how to perform the fix.</label>
              </div>
              <div class="form_field">
                &lt;?=form_textarea('desc_field[]',set_value('desc_field[]'),'class="content"');?&gt;
                &lt;?=form_error('desc_field[]');?&gt;
              </div>
            </div>
                        
                    </div>
          &lt;? endfor; ?&gt;
                    
          <div class="form_row">
            <div class="form_field">
                  &lt;?=form_button('add_more','Add Another Fix','id="add_more"');?&gt;
            </div>
          </div>
          
                    
          <div class="form_row">
            <div class="form_field">
                &lt;?=form_hidden('num',set_value('num',1),'id="num"');?&gt;
                  &lt;?=form_submit('submit','Next Step >');?&gt;
            </div>
          </div>
          
        </fieldset>
        
        &lt;?=form_close();?&gt;
Could not post full script because of char limit.
#2

[eluser]Ninjabear[/eluser]
bump
#3

[eluser]cahva[/eluser]
Seems to me like a bug in CI as it really doesnt work like the user guide says..

I quess you have to put the value the old fashioned way. For example:
Code:
&lt;input type="text" name="name[]" value="&lt;?=isset($_POST['name'][$i]) ? $_POST['name'][$i] : '' ?&gt;"&gt;
#4

[eluser]Ninjabear[/eluser]
Ignore this solution:

Partial Solution
I found a solution in a recent post. I've managed to get multidimensional arrays to work but not with proper error reporting. It remembers the values for all fields but the errors get printed for all fields.

Here is the syntax (not a full example, just important parts):
Code:
//Controller code
$this->form_validation->set_error_delimiters('<p class="error">', '</p>');
        
$this->form_validation->set_rules("name_field[]","Name of fix","trim|required|min_length[5]|max_length[100]");
$this->form_validation->set_rules("desc_field[]","Description of fix","trim|required|min_length[10]|max_length[1000]");
$this->form_validation->set_rules("url_field[]","URLs","trim|required|callback__Check_URL_Format");

$this->form_validation->set_rules("num","","trim|required");
        
if($this->form_validation->run())
{            
}
            
$this->load->view('add/step2',$options);

//Place this above your loop.
//Creates an indexed array of all of the values. You need to pad with whitespace where $num is the number of elements you have.
$names = set_value('name_field[]',array_pad( array(), $num, '' ) );
$urls = set_value('url_field[]',array_pad( array(), $num, '' ) );
$descs = set_value('desc_field[]',array_pad( array(), $num, '' ) );

$j=1;//Index beginning at one if you want it.

//loop through one of the arrays
foreach($names as $k => $v):

//Example output.
?&gt;

&lt;input type="text" name="name_field[]" value="&lt;?=$names[$k]; ?&gt;" /&gt;
&lt;?=form_error("name_field[]");?&gt;

&lt;? $j++; ?&gt;
&lt;? endforeach; ?&gt;

I've tried the set_value array style on the form_error() but it doesn't work. I need to know the params of form_error, docs don't tell you much information for example formal list of params and return types etc.
#5

[eluser]webdevguy[/eluser]
[quote author="Ninjabear" date="1284506295"]Partial Solution
I've managed to get multidimensional arrays to work but not with proper error reporting. It remembers the values for all fields but the errors get printed for all fields.
[/quote]

I've got the same problem. Subscribing...
#6

[eluser]Ninjabear[/eluser]
[quote author="webdevguy" date="1284607573"]
I've got the same problem. Subscribing...[/quote]

Webdevguy, There is a solution on this thread which I forgot to post. It explains how to override the library which incidentally has a bug:

Using Arrays as Field Names post #13

Haven't tested yet but seems like a likely solution. I imagine it manages to work the same as the docs once added. Post #14 also mentions how to implement the form once added but does not mention form_error().
#7

[eluser]Ninjabear[/eluser]
Just tested the above and the fields work / reprint the info into the form but the form validation helper doesn't seem to work with arrays either. It would be nice if someone could create an overriden version of these methods in order to correct the problem until a bug fix / v2 is released. Here is the code for the form_helper.php methods:

Code:
if ( ! function_exists('form_error'))
{
    function form_error($field = '', $prefix = '', $suffix = '')
    {
        if (FALSE === ($OBJ =& _get_validation_object()))
        {
            return '';
        }

        return $OBJ->error($field, $prefix, $suffix);
    }
}

if ( ! function_exists('validation_errors'))
{
    function validation_errors($prefix = '', $suffix = '')
    {
        if (FALSE === ($OBJ =& _get_validation_object()))
        {
            return '';
        }

        return $OBJ->error_string($prefix, $suffix);
    }
}

Unfortunately I don't have the skill to know how to update this code (if this is even the right section. I'm also assuming that you can override a helper.

Edited

Have found the lines which need to change but can't work out how to change them:

Inside form_validation.php _execute() on line 526:
Code:
if ( ! isset($this->_error_array[$row['field']]))
                {
                    $this->_error_array[$row['field']] = $message;
                }

Edited 2

I have a workaround which will work for me anyway. You can just add the following to the top of your code and print all the errors out once:

Code:
//Set the error delimiters to a list if you like
$this->form_validation->set_error_delimiters('<li class="error">', '</li>');

<ul>
&lt;?php echo validation_errors(); ?&gt;
</ul>

Hopefully this will be fixed in CI2 but just want to save others a few days work if at all possible.
#8

[eluser]webdevguy[/eluser]
[quote author="Ninjabear" date="1284652524"]Just tested the above and the fields work / reprint the info into the form but the form validation helper doesn't seem to work with arrays either. It would be nice if someone could create an overriden version of these methods in order to correct the problem until a bug fix / v2 is released. Here is the code for the form_helper.php methods:

Code:
if ( ! function_exists('form_error'))
{
    function form_error($field = '', $prefix = '', $suffix = '')
    {
        if (FALSE === ($OBJ =& _get_validation_object()))
        {
            return '';
        }

        return $OBJ->error($field, $prefix, $suffix);
    }
}

if ( ! function_exists('validation_errors'))
{
    function validation_errors($prefix = '', $suffix = '')
    {
        if (FALSE === ($OBJ =& _get_validation_object()))
        {
            return '';
        }

        return $OBJ->error_string($prefix, $suffix);
    }
}

Unfortunately I don't have the skill to know how to update this code (if this is even the right section. I'm also assuming that you can override a helper.

Edited

Have found the lines which need to change but can't work out how to change them:

Inside form_validation.php _execute() on line 526:
Code:
if ( ! isset($this->_error_array[$row['field']]))
                {
                    $this->_error_array[$row['field']] = $message;
                }

Edited 2

I have a workaround which will work for me anyway. You can just add the following to the top of your code and print all the errors out once:

Code:
//Set the error delimiters to a list if you like
$this->form_validation->set_error_delimiters('<li class="error">', '</li>');

<ul>
&lt;?php echo validation_errors(); ?&gt;
</ul>

Hopefully this will be fixed in CI2 but just want to save others a few days work if at all possible.[/quote]

I took a stab at fixing this bug in the validation class without any luck. I'm going to have to use the validation_errors() workaround from the last post with JavaScript to help the users know which fields they missed.

Can someone with more experience please write an override class to have the error messages work with individual fields that are arrays?
#9

[eluser]Unknown[/eluser]
Hey guys,
I am using CI 2.0.

set_value('foo[]') returns an array,

i wrote this MY_Form_validation extends CI_Form_validation.
It takes the $key from the POST ARRAY as you can see in that example.

Code:
example:
$this->form_validation->set_rules('field[]', 'Field', 'integer');
$_POST['field']      

Array
(
    [8] => foo
    [9] => bar
)

print_r(form_error('field[]'));

result:
Array (
       [8] => The Field field must contain an integer.
       [9] => The Field field must contain an integer.
       )
#10

[eluser]webdevguy[/eluser]
[quote author="webdevguy" date="1284717962"]
I took a stab at fixing this bug in the validation class without any luck. I'm going to have to use the validation_errors() workaround from the last post with JavaScript to help the users know which fields they missed.

Can someone with more experience please write an override class to have the error messages work with individual fields that are arrays?[/quote]

I finally got around to uploading my solution using the workaround quoted above. I posted it in Using Arrays as Field Names.




Theme © iAndrew 2016 - Forum software by © MyBB