cakePHP: form with related models not automagic updating - forms

I struggle with getting a form to work in the way I want it to behave.
I have a Regions and Properties model, one region can have many properties and so on...
I created a form to select the Region and then a Property in that region!
The form is having both lists but I struggle to have the second list [Property] updating automagic with only the properties in the region you have selected from the first list [Regions]
When you select a different region in the list, it should update automagic the property list, so you only see the properties for that region! Sorry for my bad explaining, but not sure how to explain this any better.
This is the code in my controller:
// Retrieve the region list
$this->set('regions', $this->Region->find('list', array(
'fields' => array('Region.id', 'Region.regionname'),
'order' => 'regionname',
)));
// Retrieve Property list for the regions.
$this->set('properties', $this->Region->Property->find('list', array(
'conditions' => array('Property.live' => true ),
'fields' => array('Property.id','Property.description'),
'order' => 'id',
)));
This is part of my form.
<?php echo $this->Form->create('Upload', array('action' => 'add', 'type' => 'file')); ?>
<?php echo $this->Form->input('region_id', array('label' => 'Select Region:')); ?>
<?php echo $this->Form->input('property_id', array('label' => 'Select Property:')); ?>
<?php echo $this->Form->file('file'); ?>
I have spend a lot of time looking around here and on youtube, but can't find it :-(

There's no automagic way to do what you're asking. Since all the data for dropdowns have already beed displayed on load, the only way to change the second dropdown depending on the first select is via javascript.
If you search for "dropdown on select" or something similar for cake, you'll find solutions to do it with ajax or plain js. I leave you one reference here. That one is done with ajax and a new action. But you could also do it with just js, doing a find for Regions and Properties and setting them in a json variable in js to be manipulated.

Related

CakePHP Forms, where to find and how to modify?

I'm currently new to cakephp and I just want to ask how can I accomplish this,
a select box in which I'm the one determining its options,
<?php echo $this->Form->input('treat', array('class' => 'form-control')); ?>
or how can I trace the code above to know where in the MVC did he determine his options for his selectbox. tnx
#SOS as suggested by #ndm read up on the Form Helper.
There are generally two ways to pass the options to a select via the Form Helper.
First if you have baked the application the contents of the select could be in the DB.
The Form Helper recognizes Model associations and builds the forms accordingly.Thus the contents of the select should be in the DB. For example if you have User belongsTo/hasOne UserType, the userTypes select will be populated from the DB table for userTypes.
The other way is as was already said, but unclear:
one can directly pass the options parameter of the Form->input() function.
There is another function that creates selects via the FormHelper: select().
Check it here
You can use the below code to define the options -
<?php echo $this->Form->input('treat', array(
'class' => 'form-control',
'type' => 'select',
'options' => array(
'1' => 'option 1',
'2' => 'option 2'
)
)); ?>
Just specify the options in the options array. you can also specify the blank option in that by writing 'empty'=>'Please Select' in the array list.

CakePHP 2.3.1 deactivate form validation in certain views

The Cookbook introduces for version 2.3 the possibility to deactivate the forced valiadation for forms. Or at least I understood it like that:
Quote: from http://book.cakephp.org/2.0/en/core-libraries/helpers/form.html
" New in version 2.3.
Since 2.3 the HTML5 required attribute will also be added to the input
based on validation rules. You can explicitly set required key in
options array to override it for a field. To skip browser validation
triggering for the whole form you can set option 'formnovalidate' =>
true for the input button you generate using FormHelper::submit() or
set 'novalidate' => true in options for FormHelper::create()."
In my case I have a search from for this model and of course the user does not need to fill in all mandatory fields like for adding a dataset. So I want to deactivate the validation for my search form.
I tried all three variations and see no results: Still the mandatory fields for create are mandatory in my search form.
Those attempts I made:
first try:
echo $this->Form->create('Partner', array('action' => 'search', 'novalidate' => true));
second try:
echo $this->Form->input('name',
array('required' => false, 'value' => $this->Session->read('Searchparameter.name'))
);
third try:
$this->Form->submit('Submit', array('formnovalidate' => true));
echo $this->Form->end();
variation:
echo $this->Form->end(__('Submit'), array('formnovalidate' => true));
What did I understand wrong? btw: I did deactivate caching, so that should not be the problem.
Of course I could still use the old workaround for this validation, but when 2.3 is offering this option, I would gladly use it.
Calamity Jane
So I guess I found the problem and at least got one varation working:
What I am using now is:
echo $this->Form->create('Partner', array('action' => 'search', 'novalidate' => true));
I guess what I expected was that the fields wouldn't be marked with the fat label and the asterisk. Those are still there, but regardless you don't have to fill them in anymore. And the times I tested with really submittig the form I guess I had one of the 99 varations, which was really wrong.
If that makes me happy is mine to decide, but obviously I can switch off the HTML5 validation by that.
If I would want to have the labels not bold & asterisk, is there an option, too?
Calamity Jane
The solution is actually a lot simpler. If you would like to disable validation in specific views you actually only have to refer to a non-existing model when you create the form. You could for example do something like
echo $this->Form->create('PartnerSearch');
In your controller you can access the form fields through:
$this->request->data["PartnerSearch"]["field"]
instead of the usual way:
$this->request->data["Partner"]["field"]
For me, to skip the browser validation, yes, array('novalidate' => true) does work.
<?php echo $this->Form->create('MyModelName', array('novalidate' => true)); ?>
To have the label not bold & asterisk,
<?php echo $this->Form->input('myinput', array('required' => false));
In my case I used button for submitting the form. This allowed me more flexibility. In that case I used then property 'formnovalidate' pass in the array of options for the button. The form would look something like the following:
<?php
echo $this->Form->create('yourCtrllerName',array('action'=>'actionInYourCtrller'));
echo $this->Form->input('your_field_pass',array('label'=>'pass','type'=>'password'));
.... other Form fields .....
echo $this->Form->button('Button Caption',
array('type'=>'submit',
'name'=>'keyInsideTheDataArrayForButtonData',
'formnovalidate' => true,
'value'=>'valueOfTheAboveKeyInTheDataArray',
'style'=>'<style you want to apply to button>',
... other options if needed...
)
);
echo $this->Form->end();

Displaying Zend Subform Errors in parent Zend Form

I am aware that form errors can be set to render at the top of the form using decorator code such as:
$form->setDecorators(array(
array('FormElements'),
array('FormErrors'),
However, I have subforms within my (parent) form and I need to render the subforms errors - aggregated and rendered at the top of the parent form. How can this be achieved please? Thanks.
I am a bit new to Zend but I have a similar implementation that acheives this. Although I also have extra code in here that makes the errors display in a custom manner and also puts the subforms into seperate divs.
The important parts to notice are the facts that the errors are turned off on both forms by not specifying the decorator FormErrors and then creating a new errors decorator on the parent form.
On my main form I've added a FormErrors decorator such as this:
$form->setDecorators(array(
new Zend_Form_Decorator_FormErrors(array(
'ignoreSubForms'=>false,
'markupElementLabelStart'=> '<p>',
'markupElementLabelEnd'=> '</p>',
'markupListStart'=>'<div class="formErrors">',
'markupListEnd' => '</div>',
'markupListItemStart'=>'<div>',
'markupListItemEnd'=>'</div>'
)),
'FormElements'
));
Then on the subform you turn off the form errors
$subForm->setDecorators(array(
'FormElements',
array(
array('data' => 'HtmlTag'),
array('tag' => 'div', 'class' => 'formRow')
)
));

CakePHP Form in an Element Causing Errors

I think this may be an easy solution, but I've spent an hour now investigating to no avail.
I have a registration form in an element that is being used in views belonging to different controllers. Using the "url" attribute, I've told it to submit to /users/register, but for some reason, the fields aren't submitting to the database.
Instead, there are errors for "undefined index" and a MySQL error for an undefined secondary key that I set (it's empty because it's not being submitted). Strangely, the form works fine if I include the element somewhere in the users views. Does anyone know why this is happening?
UPDATE - Here's the relevant code, sorry:
<?php
echo $form->create(array(
'id' => 'signupform',
'url' => array(
'controller' => 'users',
'action' => 'register')));
?>
The form fields are all correct, since the element works in the user controller's views anywhere. Do I need to include any other information in the creation of the form to point it more directly?
Specify the model 'User' as the first parameter to the $form->create() method.
<?php
echo $form->create('User', array(
'id' => 'signupform',
'url' => array(
'controller' => 'users',
'action' => 'register')
)
);
?>
This will ensure that the form fields are named as data[User][field_name], and prevent you from seeing that undefined index error.
Hope this works for you!
Without seeing the code, it sounds like Cake is magically assuming that the Model is the one for the controller that controls the current view. When that controller is Users, it works correctly. When it is, say, Articles, it will be trying (and failing) to fit the form fields to the Article model.
Without seeing any code, it is impossible to offer any more help.
EDIT:
If the form contains mixed models, e.g. User and Article, you must prefix the fieldnames like this:
$form->input('User.username');
$form->input('Article.title');
etc.
If you don't, the controller will assume they all belong to its own model.

Zend_Navigation overwrite with array?

I currently use zend_navigation via an XML file.
However I need to overwrite the previous breadcrumb to be its dynamic parent, in the controller.
Is this possible? It seems to me that zend_navigation is fairly static and the zend documentation keeps timing out.
Thanks
I have put:
public function addAction() {
$this->view->navigation()->addPage(array(
'type' => 'uri',
'label' => 'New page')
);
in my controller but no crumbbar shows up for that page.
Any ideas? $this->navigation() threw a
Method "navigation" does not exist and was not trapped in __call()
Also of note that my crumbBar is in my layout and not individual views.
Yes you can use an array.
What you should do really is create your array and then input it into the factory of the Zend_Navigation to create your pages for you.
Unfortunately my code is too complicated to show an example of how I used it. But I'll provide a simple example...
Once you create your navigation container, you can just add new pages to it.
Like
$this->navigation()->addPage(array(
'type' => 'uri',
'label' => 'New page'));
But you can also use addPages(). This is what I do.
I think you should just wait for the documentation to load back up for you and then look at that. Its really easy in fact.
When you have a more specific question, just ask that and give me a poke. I've had to use Navigation quite a lot so know it quite well.
Additionally, check out #zftalk on freenode. Theres lots of help on there.
// Disable Layout
$this->view->layout()->disableLayout();
$this->_helper->viewRenderer->setNoRender(true);
// Output XML than HTML
$this->getResponse()->setHeader('Content-Type', 'text/xml; charset=utf-8');
$container = new Zend_Navigation();
// Replace this section with real dynamic data.
$pages = array(
array(
'label' => 'Save',
'action' => 'save',
),
array(
'label' => 'Delete',
'action' => 'delete',
),
);
// Add pages
$container->addPages($pages);
$this->view->navigation($container);
// Output the data.
echo $this->view->navigation()->sitemap();
Additionally uses Zend Router for redirecting site.com/sitemap.xml to this controller/function.
Thank you for many developers who help me to reach here.