CakePHP validation rule automatically adding a required attribute to the field
Asked Answered
C

3

5

I am using a custom validation rule in CakePHP to be sure a value is entered into a field when a corresponding checkbox is marked:

When the "Purchasing TV" checkbox is marked, there needs to be a value in the "Enter TV Price" field.

Here's the validation rule within my model's validation array...

'tv_price'=>array(        
    'check'=>array(
        'rule'=>array('check_for_tv_price'),
        'message'=>'Please enter the television pricing information.',
    ),
)

...and here's my really simple custom validation function:

public function check_for_tv_price($check) {
    if($this->data['Client']['tv']==1&&$this->data['Client']['tv_price']=="") {
        return false;
    }
    if($this->data['Client']['tv']==1&&$this->data['Client']['tv_price']!="") {
        return true;
    }
    if($this->data['Client']['tv']==0) {
        return true;
    }

}

I've tried adding 'required'=>false and 'allowEmpty'=>true at different points in the validation array for my tv_price field, but they always override my custom rule! As a result, a user can not submit the form because the browser prevents it (due to the required attribute).

For reference, the browser spits out the following HTML:

<input id="ClientTvPrice" type="text" required="required" maxlength="255" minyear="2013" maxyear="2018" name="data[Client][tv_price]"></input>

(Note the minyear and maxyear attributes are from the form defaults.)

Has anyone found a way to prevent the automatic insertion of the required attribute when using custom validation rules?

Any guidance would be much appreciated.

Thanks!

Chris

Crore answered 26/4, 2013 at 23:34 Comment(1)
How such a simple task can be so difficult blows my mind... There still isn't a good solution for this. It seems that one cannot allow a text input to be blank, yet run the rest of the validations/custom validations defined. Frustrating as hell...Pasadis
Z
11

Set required to false and allowEmpty to true, that should do it for you.

'tv_price'=>array(        
    'check'=>array(
        'rule'=>array('check_for_tv_price'),
        'message'=>'Please enter the television pricing information.',
        'required' => false,
        'allowEmpty' => true
    ),
)

Hope this helps.

Zeuxis answered 27/4, 2013 at 0:9 Comment(2)
'required' => false is not necessary, it's null by default. Just the 'allowEmpty' => true is enough to ensure the 'required' attribute is not added to the input element.Skull
Thanks, @kaisok! I've added 'allowEmpty'=>true to the validation array and it appears to be working. I've turned on the required attribute when the checkbox is checked (see above for the JS code)Crore
V
1

These seems like 2.3's new HTML5 magic stuff.

Try adding 'formnovalidate' => true to the $this->FormHelper->input() options in the view.

ref:
http://book.cakephp.org/2.0/en/appendices/2-3-migration-guide.html#formhelper
http://book.cakephp.org/2.0/en/core-libraries/helpers/form.html#FormHelper::input

Vacillating answered 27/4, 2013 at 5:7 Comment(0)
C
0

Thank you for the input!

Upon further investigation, I actually do want the required attribute turned on when the form is checked; to achieve this I wrote two simple JavaScript functions (and used a third that I found online) to check the current status of the checkboxes and mark the field as required when appropriate.

In the view file, I added the function calls in two locations. The first block is in the onload function and is called when the window is loaded:

<script type="text/javascript">
    window.onload = function() {
        toggle_setup(document.getElementById('ClientTv'), 'tvPrice', false)
        toggle_required(document.getElementById('ClientTv'), "ClientTvPrice")
    }
</script>

These are a mess, I know. But they worked!

Note the fields that appear when the checkbox is clicked are enclosed in a div with a name that is used in the toggle_setup function to show or hide the div as needed. In this case, I named the div 'tvPrice'

<?php echo $this->Form->input('Client.tv', array('label'=>'Purchasing TV? <small>(Check if Yes)</small>', 'onclick'=>'toggle_setup(this, "tvPrice", "TV pricing");toggle_required(this, "ClientTvPrice")'));
echo $this->Form->input('Client.tv_price', array('label'=>'Enter TV Price','div'=>array('class'=>'hidden', 'id'=>'tvPrice')));
 ?>

And here are the JavaScript functions themselves:

function toggle_required(element, id) {
    var object = document.getElementById(id)
    if(element.checked) {
        object.setAttribute( 'required', "required")
    } else {
        object.removeAttribute('required')
    }    
}
function toggle_setup(element, div, human_term) {
    if(element.checked) {
        document.getElementById(div).style.display='block'
    } else {
        if(!human_term) {
            clearChildren(document.getElementById(''+div))
            document.getElementById(div).style.display='none'
        } else {
            if(confirm('Are you sure you want to clear the client\'s '+human_term+' settings?')) {
                 clearChildren(document.getElementById(div))
                 document.getElementById(div).style.display='none'
            } else {
                element.checked = true
            }
        }
    }

}
function clearChildren(element) {
   for (var i = 0; i < element.childNodes.length; i++) {
      var e = element.childNodes[i];
      if (e.tagName) switch (e.tagName.toLowerCase()) {
         case 'input':
            switch (e.type) {
               case "radio":
               case "checkbox": e.checked = false; break;
               case "button":
               case "submit":
               case "image": break;
               default: e.value = ''; break;
            }
            break;
         case 'select': e.selectedIndex = 0; break;
         case 'textarea': e.innerHTML = ''; e.value=""; break;
         default: clearChildren(e);
      }
   }
}

The above code uses a CSS class called "hidden" which I've defined as below:

.hidden {
    display: none;
}

Per the above suggestions, I've added the 'required'=>false and 'allowEmpty'=>true lines to my validation array and it appears to be working.

Thank you for all the help!

Crore answered 30/4, 2013 at 21:53 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.