jQuery and Required form fields

I use a jQuery show/hide effect to show/hide form fields based on what radio option is selected.

For example:


<label for="car">Car</label>

<input name="vehicle_type" id="car" type="radio" value="Car" />


<label for="boat">Boat</label>

<input name="vehicle_type" id="boat" type="radio" value="Boat" />


<div id="car_make_div" style="display:none">

<input type="text" id="car_make" name="car_make" />

</div>


<script type="text/javascript">

$('input[name=\'vehicle_type\']').change(function(){

if($('input[name=\'vehicle_type\']:checked').val() == 'Car')

{

	$('#car_make_div').show();

}

if($('input[name=\'vehicle_type\']:checked').val() == 'Boat')

{

	$('#car_make_div').hide();

}

</script>



In my example, the input field ‘car_make’ is a required field in the model. How can I make it be “required” only if is being displayed?

Anyone able to advise?

You should use scenarios in your model. view http://www.yiiframework.com/doc/guide/form.model#triggering-validation

In your controller you should check which radio option is selected and then set the appropriate scenario when creating the model.

Hi GDzyne,

Basically I use jQuery to show/hide fields on the page. The controller will not know which radio option has been selected… do you mean I should send an ajax call to the controller to change the scenario?

Hi GSTAR,

If I understand correctly you will be submitting the form to be processed (saved to DB) ?

If so, then in your action method of your controller you will need to check which option is checked.





In controller :


...

$scenario=$_POST['vehicle_type'];

$model=new Model($scenario);

// rest of assignment

...


In model :


...

public function rules()

{

    return array(

        array('car_make', 'required', 'on'=>'Car'),

        array('boat_make', 'required', 'on'=>'Boat'),

    );

}

...




Hi Gdzyne,

Thanks for that. However the problem with that now is upon first page load those fields are not rendered as required, i.e. we don’t have “label class=required”. So the user wil not know that the field is required until after the form has been submitted and they are given the error.

Any suggestion on how to rectify this?

You can manually set in htmlOptions the class required for the label.

How can you check multiple scenarios? For example this is what I have done in my controller action, not sure if it is correct:




if(isset($_POST['vehicle_type']))

{

	$scenario=$_POST['vehicle_type'];

	$model=new Vehicle($scenario);

}

else

{

	$model=new Vehicle;

}



The above code does a check on the vehicle type field, what if I also need to do a check on another field?

I’d suggest reading through the documentation and trying stuff out, once you understand how these work it will make things much easier… http://www.yiiframework.com/doc/guide/form.model#triggering-validation

You can have a 100 (or as many as you want) seniores all with different fields or variation of fields.




$model=new Vehicle('Car');

$mode->attributes = $_POST['car'];

$model->validate();


//you can check multiple scenarios by changing it and running the validate method

$mode->setScenario("ANOTHER_ scenario");

$mode->validate();

//though you could run into problems if you don't fully understand how these work


//you can also individually validate fields if need be

$model->validate("car_make");


//rules

public function rules()

{

    return array(

        array('car_make', 'required', 'on'=>'Car'),

        array('boat_make', 'required', 'on'=>'Boat'),

        array('can_fly', 'require', 'on' => "Car, Airplane, UFO"),

        array('price', 'require', 'on' => "Car, UFO"),

    );

}




The best way is probably to just use rules! You can target multiple fields by using the ON option;

e.g. the can_fly field will only be required if the scenario is Car, Airplane, UFO but the price will only be required if the scenario is CAR or UFO.

Cheers Sniper ;)

I have my rules defined to perform the checks, but I’m having difficulty in checking the scenarios in my controller. This is what I have now:

Rules:




array('car_make', 'required', 'on'=>'Car'),

			

array('return_datetime', 'required', 'on'=>'Home'),



Controller:




public function actionForm()

{

	$model=new Enquiry;

	

	if(isset($_POST['vehicle_type']))

	{

		$scenario=$_POST['vehicle_type'];

		$model->setScenario($scenario);

	}

	if(isset($_POST['journey_from']))

	{

		$scenario=$_POST['journey_from'];

		$model->setScenario($scenario);

	}

	

	if(isset($_POST['Enquiry']))

	{

		$model->attributes=$_POST['Enquiry'];

			

		if($model->validate())

		{

			// processing here

		}

	}

	

	$this->render('index', array('model'=>$model));

}



I can’t seem to check multiple scenarios, it will only check one at a time.

You need to call $model->validate() after setting each scenario, otherwise it will only check the last scenario that was set.

That has not worked I’m afraid. It still only takes in to account the last scenario that was set.

can you post the controller code?

call var_dump($model->getScenario()) after $model->setScenario() this should print a different scenario name after each call, if its blank then something is wrong with your post request!

The controller code is posted in an above post.

I think because both scenarios are active, $model->setScenario($scenario); just gets overwritten with the latest call!

The code should have changed by now the above code will not work!!

OK check it then:

Rules:




array('car_make', 'required', 'on'=>'Car'),

			

array('return_datetime', 'required', 'on'=>'Home'),



Controller:




public function actionForm()

{

	$model=new Enquiry;

	

	if(isset($_POST['vehicle_type']))

	{

		$scenario=$_POST['vehicle_type'];

		$model->setScenario($scenario);

		$model->validate();

	}

	if(isset($_POST['journey_from']))

	{

		$scenario=$_POST['journey_from'];

		$model->setScenario($scenario);

		$model->validate();

	}

	

	if(isset($_POST['Enquiry']))

	{

		$model->attributes=$_POST['Enquiry'];

			

		if($model->validate())

		{

			// processing here

		}

	}

	

	$this->render('index', array('model'=>$model));

}



So in my form, $_POST[‘vehicle_type’] is “Car” and $_POST[‘journey_from’] is “Home”. This should mean that both ‘car_make’ and ‘return_datetime’ fields should be required. At the moment, only ‘return_datetime’ field is showing as an error.

Each time you call validate() it resets the previous error messages because they were for a different scenario! so you need to build an array of errors to use later.

so after each ->validate call you need to collect the errors by calling $model->getErrors() (adding them to new array $allErrors) and after the last validate set the errors again $mode->addErrors($allErrors)

Can’t get it to work! Post some code for us, modify my code above!

Anyone able to advise?

Can you post the code you tried with the getErrors() and addErrors() function calls.