CakePHP Form in an Element Causing Errors - forms

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.

Related

How to access backpack fields on custom (non-CRUD) page?

I've made a custom page in backpack admin panel. This page is non-CRUD (not related to any model). There are several forms on it, with date pickers, select inputs, etc. So I'am trying to find a way to use backpack fields to create these date pickers and select inputs. Because it seems to be awkward to embed custom js-controls into the project, as Backpack already has appropriate fields.
The only solution I came up with, is to create a crud controller for random model, disable all operations except create, use create operation view as custom page (backpack fields are available this way), and finally override store() method - to prevent creating new model entry in DB.
So, is there a proper way to access backpack fields on custom (non-CRUD) page?
Backpack 4.x fields aren't meant to be used outside CRUDs, but you can do that.
Option A
At their core, Backpack fields are just Blade views, so you can load them using the Blade helper #include(). Just make sure to pass along all variables that the blade file needs. I believe in 99% of the fields that will be a $field and a $crud variable, so this will work:
#php
// set the CRUD model to something (anything)
// but ideally it'd be the model of the entity that has the form
$crud = app()->make('crud');
$crud->setModel(\App\Models\Monster::class);
#endphp
#include('crud::fields.number', [
'crud' => $crud,
'field' => [
'name' => 'price',
'label' => 'Price',
'prefix' => '$'
]
])
This way, you only load the bits you actually want (the inputs), without the overhead of a CrudController. You can point the form to your custom controller and do the saving yourself. What you need to pass for a $field above is a Backpack field definition in array form.
This way is super-simple, but it has a big downside if you ask me. The field definition has to be 100% correct and complete, you lose all the magic and assumption logic that Backpack usually does to make your life easier when you add field using addField(). That's why in most cases I think it's more convenient to go with Option B.
Option B
Instead of manually loading all each field Blade view, add them using addField(), then load all of them just like Backpack does it in the Create or Update operation:
#php
$crud = app()->make('crud');
$crud->setModel(\App\Models\Monster::class);
$crud->addField([
'name' => 'price',
'label' => 'Price',
'prefix' => '$'
]);
#endphp
<form method="post">
#include('crud::form_content', [ 'fields' => $crud->fields(), 'action' => 'create' ])
</form>
The above will produce an output like this:
The benefit of this second option is that you can "forget" to mention stuff in the field definition and Backpack will assume it, you can use the fluent syntax, you can use most Backpack features, really...

How to pass params in url to a backpack create form

I'm using backpack 3.3 on a laravel 5.5 installation.
I want to prefill two create form fields with two URL passed values.
Say you create a basic backpack crud, named Image.
Normally you can go to domain/admin/image/create to view and fill in the form.
But if I add one or two params in the url, I get a 404.
I guess I should manage the routes file (admin.php)
I tried this way:
Route::group(['prefix' => 'image/{k}/{cid}'], function()
{
CRUD::resource('image', 'ImageCrudController');
});
but still get a 404.
Any suggestions?
Thanks in advance.
Almost all field types have a default option. So when you define them, you can specify a default. And you can always pass a GET parameter for that default. So you can have something like this in your EntityCrudController:
$this->crud->addField[ // Text
'name' => 'title',
'label' => "Title",
'type' => 'text',
'default' => \Request::has('title')?\Request::has('title'):false, // default value
]);
You'd then be able to send you users to yourapp/admin/entity/create?title=your+default+value and have that default value show up in the field.
Hope it helps. Cheers!
it works for me easier
http://127.0.0.1:8000/admin/resultado/create?competencia=2
$this->crud->modifyField("competencia_id",[
'label' => "Competencia",
"default"=>$this->crud->request->query->get('competencia'),
.....

cakePHP: form with related models not automagic updating

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.

"Repeated" group in Forms for password validation

I am using the 'repeated' field to validate a password in the form.
According to the documentation, the 'repeated' field group is supposed
to, render two identical fields (which it is doing) and submit only if
the values from both the fields match or it should throw a validation error. The
second part somehow does not seem to work. I tried using the example
code as is but, the form submits with no issue or error even if the
passwords do not match. Did anyone else come across the same issue or
is there something I am doing wrong?
I did not add a validation file nor do I use annotations. From what I understand from the documentation, the repeated filed checks the values from first_name and second_name fields automatically and submits the form only when both the values are equal which it is not doing. This is the code I am using,
->add('password', 'repeated',
array(
'type' => 'password',
)
)
This renders two fields 'First' and 'Second' and passes an array with the 'First' and 'Second' values on submit.
the correct syntax would be
->add('tmpPassword', 'repeated', array('type' => 'password'));
if you use the the same key for the field as for the type it can not assign the value correct.
It turns out it was a stupid mistake on my part. I was not validating the form in the controller. Once, I do that it works fine.

Write hyperlink inside the Zend Form and use routes?

I am having a Log-in form and want to add a "Lost Password" Link inside. I found out that you can use the description to do so. But I have now started to change everything to work with routes and would like to use this also for the Forgot Password Link. is there any chance to do this? I can't find a solution, anyone of you who knows how to do it?
$password = new Zend_Form_Element_Password('login_password', array(
'label' => 'Password',
'description' => 'Forgot Password ?',
'required' => true,
));
$password->getDecorator('description')->setOptions(array('escape' => false, 'placement' => 'APPEND'));
I've faced the same problem before, and got answer at
Write hyperlink inside the Zend Form?
May help you also...
When creating a Zend_Form, you don't have access to View_Helpers, as a form does not require a view instance. Therefore you either have to fetch a view in your form's init-method or add the description later (I prefer the latter).
When doing it the first way, you have to fetch the Zend_Controller_Front-instance and then its view, finally call a view helper, e.g. Zend_View_Helper_Url from that view.
The latter can be achieved by adding the description later on, e.g. when you passed the form to your view (or in your controller before passing it to the view):
<?php
$description = '<a href="' . $this->url([...]); . '"'>forgot password?</a>
$this->form->getElement('login_password')->setDescription($description);
echo $this->form;
?>