CodeIgniter Forums
Form Generation Library - Printable Version

+- CodeIgniter Forums (https://forum.codeigniter.com)
+-- Forum: Archived Discussions (https://forum.codeigniter.com/forumdisplay.php?fid=20)
+--- Forum: Archived Libraries & Helpers (https://forum.codeigniter.com/forumdisplay.php?fid=22)
+--- Thread: Form Generation Library (/showthread.php?tid=16439)



Form Generation Library - El Forum - 08-12-2011

[eluser]Ttj9a[/eluser]
I have noticed that a couple of people have posted about (at least) checkbox fields not being correctly populated when validation has failed.

It seems like a probable source of the problem is the way the form_validation library 'set_value' function behaves. When the submitted data is an array (e.g. multiple checkboxes) then the 'set_value' function uses the 'array_shift' function on the posted data. (see code from Form_validation.php, lines 726-741)
Code:
function set_value($field = '', $default = '')
    {
...
        // If the data is an array output them one at a time.
        //     E.g: form_input('name[]', set_value('name[]');
        if (is_array($this->_field_data[$field]['postdata']))
        {
            return array_shift($this->_field_data[$field]['postdata']);
        }

        return $this->_field_data[$field]['postdata'];
    }
The result of this is that each time 'set_value' is executed, it returns *one* of the values submitted, and will not return this value again.
This is a problem, because the block of code:
Code:
case 'checkbox':
case 'radio':
$checked = set_value($name);
$this->$element->atts['checked'] = ($checked && in_array($this->$element->value, $checked)) ? TRUE : FALSE;
break;
executes once per checkbox in the list of checkboxes. The first time it runs, you get the first value from the submitted checkbox array (which may actually be the value associated with the second checkbox if the first wasn't checked). The second time it runs, you get the second value from the submitted checkbox array.

The long and the short of it is this: either set_value is not the right function to use, or it needs to be run multiple times, the returned data stored (e.g. in an array) and then the $checked status matched against the contents of the array.

I'll probably hack something up to do that, but it will probably not be pretty (nor in the theme of the library).

For reference: I'm using CodeIgniter 2.0.2 on Win64 platform (using wamp).


Form Generation Library - El Forum - 08-12-2011

[eluser]Ttj9a[/eluser]
Ok, so my hack of a fix to resolve the issue of checkboxes not being correctly detected as checked is this:

Change line 3 of the following block of code so it goes from:
Code:
case 'checkbox':
case 'radio':
$checked = set_value($name);
$this->$element->atts['checked'] = ($checked && in_array($this->$element->value, $checked)) ? TRUE : FALSE;
break;

Code:
case 'checkbox':
case 'radio':
$checked = (substr($name,-2,2) == '[]') ? get_instance()->input->post(substr($name,0,-2)) : get_instance()->input->post($name);
$this->$element->atts['checked'] = ($checked && in_array($this->$element->value, $checked)) ? TRUE : FALSE;
break;

Also seems to fix the 'array' problem that had previously been discussed.


Form Generation Library - El Forum - 08-16-2011

[eluser]Ttj9a[/eluser]
I just ran into a new problem with this library, using the 'set_value' function.
I have a large list of fields, and am populating their values from a database. It is possible that the values returned from the database are blank (and that is ok; not all fields need be completed).

To set the values, I have basically been doing:
Code:
$this->form->set_value('field1name',$db_data[0]['col1name']);
$this->form->set_value('field2name',$db_data[0]['col2name']);
...
$this->form->set_value('field10name',$db_data[0]['col10name']);

The problem is that I do all of this after setting up all the fields, so my code is:
Code:
$this->form->br()->checkgroup('field10name', $options, 'Fieldname', '', 'xss_clean');
$this->form->submit();
$db_data = $this->mymodel->get_data();
if ($db_data !== null) {
   $this->form->set_value('field1name',$db_data[0]['col1name']);
   $this->form->set_value('field2name',$db_data[0]['col2name']);
   ...
   $this->form->set_value('field10name',$db_data[0]['col10name']);
}

The consequence of this is that if the data for the last field ($db_data[0]['col10name']) is empty, then the value of my submit button is set to 'field10name'.
The reason for this is that the set_value function examines whether the arguments are blank in order to determine which form of the function to use (i.e. you can pass just a value, or you can pass a field name and value). If the 'value' - the second argument - is blank/null/whatever (i.e. !$value) then it is assumed the first field is a value, and the most recently created form item is given that value.

So basically the problem is that the function is:
Code:
function set_value($name='', $value='')
   if ($this->_last_accessed && !$value) {
       //assume that since there was no value, we should be updating the last accessed field

That's fine, unless you actually want to update a field with a blank.

I figure there are a couple of ways to resolve this, but each has problems.
First, it would be possible to change the function to actually use null as the default value, and then match to an actual null.
Code:
function set_value($name='', $value=null)
   if ($this->_last_accessed && ($value === null)) {

Of course, then if an actual null is passed (which is, really, a legitimate possibility for a field value) then it still doesn't work.
Another alternative is to set the default values to something absurd; something which is probably never going to be appear as a legitimate value, and then check for that.
Code:
function set_value($name='', $value='zee_monkeys_have_taken_over_zee_world')
   if ($this->_last_accessed && ($value == 'zee_monkeys_have_taken_over_zee_world')) {
Of course, that is a filthy hack, and on the offchance someone actually wanted to use that value then problems would occur. The problems would be less likely than using the blank, but still possible.

I imagine there is a very tricky option involving using a private anonymous function, and comparing pointers or something crazy like that. I'm not going to try that at this stage, because it seems like a lot of hard work at a bit risky.

The final option, of course, is for users to simply check if they are about to try to set the value to blank, and not do it (but that is only really an option if you don't actually want to override an existing value with blank, in which case you're screwed).

Anyway, for the moment my Form.php is going to involve monkeys taking over the world.

P.S. I should not that you also need to comment out one line in the code as well, otherwise you will get a 'set_value: no value specified' error (because blank values can now get to this point in the code, whereas they couldn't before).
Code:
function set_value($name='', $value = 'zee_monkeys_have_taken_over_zee_world')
    {        
        if (($this->_last_accessed) && ($value == 'zee_monkeys_have_taken_over_zee_world'))
        {
            if (!$name) show_error(FGL_ERR.'set_value: No value specified');

            $value = $name;
            $el = $this->_last_accessed;
        }
        else
        {
            if (!$name) show_error(FGL_ERR.'set_value: No element name specified');
//comment out this line:        //if (!$value) show_error(FGL_ERR.'set_value: No value specified');

            $el = $this->_el_get_unique($name);
        }



Form Generation Library - El Forum - 04-16-2012

[eluser]mk-dev[/eluser]
Hi, and thanks for the great job.
I have a question about using 2 or more form in the same page.
I think I followed your doc (about the clear method) but I don't get what I'd like.
Here's my code:

$this->load->library('form');
$this->form->text('testo','testo','required|numeric|trim|max_length[2]');
$this->form->text('testo2','testo2','trim|required|matches[testo]');
$this->form->submit('invia1');

$this->data['form1'] = $this->form->get();
$this->form->clear();

$this->form->text('testo3','testo3','trim|required|numeric');
$this->form->submit('invia2');

$this->data['form2'] = $this->form->get();

$this->form->validate();

if ($this->form->valid) {
if ( $this->input->post('invia1') ) {
die('ok: 1'.anchor('test/fmform','go back'));
} else {
die('ok: 2'.anchor('test/fmform','go back'));
}
}


$this->data['errors'] = $this->form->errors;
$this->load->view('fmform',$this->data);

what happens is that the field in the second form generates an error if I submit the first form. I also tried separating the error messages after the $this->form->get(), but it doesn't seem to work (only errors from the first form appear).
Before looking at the code, I'd like to know if this is the way I'm supposed to do it.

Thank you.


Form Generation Library - El Forum - 04-16-2012

[eluser]mk-dev[/eluser]
[quote author="mk-dev" date="1334567882"]Hi, and thanks for the great job.

what happens is that the field in the second form generates an error if I submit the first form. I also tried separating the error messages after the $this->form->get(), but it doesn't seem to work (only errors from the first form appear).

Thank you.[/quote]

the last sentence was my mistake. Now I get errors for both forms, but it looks like it wants to validate both, instead of only the one that was posted.

I tried to use if to add/remove the 'required' validation based on which form was posted, but I still get errors from both forms.


Form Generation Library - El Forum - 04-17-2012

[eluser]predat0r[/eluser]
Hi,

I have a strange problem with validation, I get an error message "- Unable to access an error message corresponding to your field name." when I fill out all the fields correctly. I don't know where it comes from.
If I have for example 4 input fields, and I click on Submit, I get the 4 error messages, and plus 1 for unknown input. I tried to disable CSRF (that generates hidden input field), but result is the same.

Any idea why? How is it possible?

EDIT: found the problem. Submitting form the lib sends the submit button to validate, and of course it hasn't error message set. So hacking the lib now works:

function validate()
Code:
foreach ($this->_elements as $el)
   {
    if ($el['name'])
    {
     if($el['name'] != 'submit')
      {
      $name   = $el['name'];
      $element  = $el['unique'];
      $type   = $el['type'];
      
      $label = ( ! empty($this->$element->label_text)) ? $this->$element->label_text : ucfirst($element);
      
      if ( ! empty($this->$element->rules))
      {
       if ( ! empty($this->$element->group_label)) $label = $this->$element->group_label;
       if ( ! empty($this->$element->err_label)) $label = $this->$element->err_label;
       $this->CI->form_validation->set_rules($name, $label, $this->$element->rules);    
      }
      else
      {
       $this->CI->form_validation->set_rules($name, $label);
      }
     }
    }  
   }



Form Generation Library - El Forum - 04-19-2012

[eluser]Yednotek[/eluser]
Is it me or is it impossible to add multiple attributes to a textfield?

Code:
$attributes = array(
            'class'=>"input-large",
            'placeholder'=>"Fill me out"
        );

$this->form->open('formTest')
    ->text('city2|city2','','','',$attributes);

The resulting HTML only has the class="input-large" attribute.
Is the placeholder attribute not allowed for some reason?





Form Generation Library - El Forum - 04-20-2012

[eluser]Unknown[/eluser]
[quote author="Yednotek" date="1334866812"]Is it me or is it impossible to add multiple attributes to a textfield?

Code:
$attributes = array(
            'class'=>"input-large",
            'placeholder'=>"Fill me out"
        );

$this->form->open('formTest')
    ->text('city2|city2','','','',$attributes);

The resulting HTML only has the class="input-large" attribute.
Is the placeholder attribute not allowed for some reason?


[/quote]


Yeah I stumbled upon the same problem and after some digging in the library I found out that, for some strange reason, there is a list of valid attributes for each form field ! (around the line 95 of Form.php file) So I changed it with the follwing code to allow the attributes 'placeholder' and 'autocomplete' in case you want to turn it off for some input fields:

Code:
var $_valid_atts = array(
  'label'  => 'accesskey|onblur|onfocus|class|style|title|dir|lang', // 'for' not included, supplied with form helper function
  'form'   => 'action|accept|accept-charset|enctype|method|name|onreset|onsubmit|target',
  'input'  => 'accept|accesskey|align|alt|checked|disabled|ismap|maxlength|name|onblur|onchange|onfocus|onselect|readonly|size|src|tabindex|type|usemap|value|autocomplete|placeholder',
  'select'  => 'disabled|multiple|onblur|onchange|onfocus|size|tabindex', // 'name' not included, supplied with form helper function
  'textarea' => 'cols|rows|accesskey|disabled|name|onblur|onchange|onfocus|onselect|readonly|tabindex|placeholder',
  'button'  => 'accesskey|disabled|name|onblur|onfocus|tabindex|type|value|content', // 'content' added, supplied with form helper function
  '*'   => 'class|id|style|title|dir|lang|onclick|ondblclick|onmousedown|onmouseup|onmouseover|onmousemove|onmouseout|onkeypress|onkeydown|onkeyup|rel|data-value'
);

Enjoy!


Form Generation Library - El Forum - 04-22-2012

[eluser]Yednotek[/eluser]
[quote author="Sidou" date="1334941371"]

Yeah I stumbled upon the same problem and after some digging in the library I found out that, for some strange reason, there is a list of valid attributes for each form field ! (around the line 95 of Form.php file) So I changed it with the follwing code to allow the attributes 'placeholder' and 'autocomplete' in case you want to turn it off for some input fields:

Code:
var $_valid_atts = array(
  'label'  => 'accesskey|onblur|onfocus|class|style|title|dir|lang', // 'for' not included, supplied with form helper function
  'form'   => 'action|accept|accept-charset|enctype|method|name|onreset|onsubmit|target',
  'input'  => 'accept|accesskey|align|alt|checked|disabled|ismap|maxlength|name|onblur|onchange|onfocus|onselect|readonly|size|src|tabindex|type|usemap|value|autocomplete|placeholder',
  'select'  => 'disabled|multiple|onblur|onchange|onfocus|size|tabindex', // 'name' not included, supplied with form helper function
  'textarea' => 'cols|rows|accesskey|disabled|name|onblur|onchange|onfocus|onselect|readonly|tabindex|placeholder',
  'button'  => 'accesskey|disabled|name|onblur|onfocus|tabindex|type|value|content', // 'content' added, supplied with form helper function
  '*'   => 'class|id|style|title|dir|lang|onclick|ondblclick|onmousedown|onmouseup|onmouseover|onmousemove|onmouseout|onkeypress|onkeydown|onkeyup|rel|data-value'
);

Enjoy![/quote]

Thanks for pointing that out! Seems a bit strange to restrict the allowed attributes like that, takes away some flexibility as we see now. But will update the file. Thanks again Sidou!


Form Generation Library - El Forum - 04-22-2012

[eluser]Unknown[/eluser]
I am confuse about the code, anyone can help me to explain what is mean? thanks