I am using Symfony with propel to generate a form called BaseMeetingMeetingsForm.
In MeetingMeetingsForm.class.php I have the following configure method:
public function configure() {
$this->useFields(array('name', 'group_id', 'location', 'start', 'length'));
$this->widgetSchema['invited'] = new myWidgetFormTokenAutocompleter(array("url"=>"/user/json"));
}
In MeetingMeetings.php my save method is simply:
public function save(PropelPDO $con = null) {
$this->setOwnerId(Meeting::getUserId());
return parent::save($con);
}
However propel doesn't know about my custom field and as such doesn't do anything with it. Where and how to I put in a special section that can deal with this form field, please be aware it is not just a simple save to database, I need to deal with the input specially before it is input.
Thanks for your time and advice,
You have to define a validator (and/or create your own). The validator clean() method returns the value that needs to be persisted.
In Doctrine (I don't know Propel) the form then calls the doUpdateObject() on the form, which in turns calls the fromArray($arr) function on the model.
So if it's already a property on your model you'll only need to create the validator. If it's a more complex widget, you'll need to add some logic to the form.
Related
I want to create readonly hidden field. Now I have field that looks like this:
$builder
->add('question_category_id', HiddenType::class);
And entity has method:
public function getQuestionCategoryId() {
return $this->getQuestion()->getQuestionCategory()->getId();
}
After saving I got following error:
Neither the property "question_category_id" nor one of the methods "addQuestionCategoryId()"/"removeQuestionCategoryId()", "setQuestionCategoryId()", "questionCategoryId()", "__set()" or "__call()" exist and have public access in class "Entity\UnitQuestionAnswer".
I could add dummy method
public function setQuestionCategoryId($id) {
return $this;
}
but it is not right way.
How to create readonly hidden field, or avoid of writing back data from from into entity?
S2.8 has a read_only attribute which would do what you want but it has been removed in 3.0.
The disabled attribute should work. Just be aware that the value itself will not actually be submitted symfony.com/doc/current/reference/forms/types/… so if you are doing anything funky with the posted data then that could be a problem.
I suppose it's possible to fool around with the internals but that would be more trouble than it is worth.
Personally, given that my get method was added just for the form, I would just add a corresponding set method and move on.
Assume for a moment that this form utilizes an imaginary Animal document object class from a ZooCollection that has only two properties ("name" and "color") in symfony2.
I'm looking for a working simple stupid solution, to pre-fill the form fields with the given object auto-magically (eg. for updates ?).
Acme/DemoBundle/Controller/CustomController:
public function updateAnimalAction(Request $request)
{
...
// Create the form and handle the request
$form = $this->createForm(AnimalType(), $animal);
// Set the data again << doesn't work ?
$form->setData($form->getData());
$form->handleRequest($request);
...
}
You should load the animal object, which you want to update. createForm() will use the loaded object for filling up the field in your form.
Assuming you are using annotations to define your routes:
/**
* #Route("/animal/{animal}")
* #Method("PUT")
*/
public function updateAnimalAction(Request $request, Animal $animal) {
$form = $this->createForm(AnimalType(), $animal, array(
'method' => 'PUT', // You have to specify the method, if you are using PUT
// method otherwise handleRequest() can't
// process your request.
));
$form->handleRequest($request);
if ($form->isValid()) {
...
}
...
}
I think its always a good idea to learn from the code generated by Symfony and doctrine console commands (doctrine:generate:crud). You can learn the idea and the way you should handle this type of requests.
Creating your form using the object is the best approach (see #dtengeri's answer). But you could also use $form->setData() with an associative array, and that sounds like what you were asking for. This is helpful when not using an ORM, or if you just need to change a subset of the form's data.
http://api.symfony.com/2.8/Symfony/Component/Form/Form.html#method_setData
The massive gotcha is that any default values in your form builder will not be overridden by setData(). This is counter-intuitive, but it's how Symfony works. Discussion:
https://github.com/symfony/symfony/issues/7141
everyone. I've started using atk4 in a personal project a couple weeks ago and have been facing some difficulties since then. This specific question I want to ask is about how to make form validations when using the CRUD component shipped with the atk4 framework.
I have already tried several different solutions, none of them solving my problem.
I have a feeling that the problem here might be that the form validation happens within the call of the method $form->isSubmitted() (am I correct?). Since when using a CRUD component within a Page we don't use that way of processing the form submission, we'd have to find alternatives to it. For example, let's say I have a Page with the following init() function:
function init() {
parent::init();
// create a CRUD and set a model to it
$crud = $this->add('CRUD');
$m = $crud->setModel('Person');
if ($crud->form) {
$fn = $crud->form->getField('first_name');
$fn->validateNotNull('The first name must not be empty.');
}
}
Even though I've added the validation to the first name field, it won't be validated. I've tried several things, unsuccessfully. I tried to extend the CRUD class and reimplement the formSubmit($form) function, adding the validation there. Even if I do it, it doesn't work.
Originally (in the CRUD class), there is the function:
function formSubmit($form){
$form->update();
$this->api->addHook('pre-render',array($this,'formSubmitSuccess'));
}
I tried to iterate through the form's fields and call its validate() method, but it didn't work. Also, if I try to do alter the function (in a MyCRUD class, let's say) like below,
function formSubmit($form){
if ($form->isSubmitted()) {
$form->update();
$this->api->addHook('pre-render',array($this,'formSubmitSuccess'));
}
}
there happens an infinite loop... Could someone help me out?
[EDIT]
One last question intimately related to this one. I've just tried to do the exact same validation proposed by romanish below but, instead of adding a CRUD to a page, I was just adding a Form, and it doesn't work -- though the CRUD does work. Instead, there happens a "Error in AJAX response: SyntaxError: Unexpected token
CRUD component respects the validation you're doing inside the model. When data is entered into the form and button is clicked, $model->update() is called.
The execution continues into beforeUpdate() hook, which is the one you need to intercept.
http://agiletoolkit.org/learn/understand/model/actions
class Model_Book extends Model_Table {
function init(){
parent::init();
// .... more definitions ...
$this->addHook('beforeSave',$this);
}
function beforeSave(){
if(strlen($this['book_name']<10))
throw $this->exception('Name of the book is too short')
->setField('book_name');
}
If model is unable to save itself and will produce exception, Form automatically show it as a field error.
I would like to validate an embedded form field before it gets saved in the database. Currently it will save an empty value into the database if the form field is empty. I'm allowing empty fields, but I want nothing inserted if the form field is empty.
Also quick question, how to alter field values before validating/saving an embedded form field?
$this->form->getObject works in the action, but $this->embeddedForm->getObject says object not found
I found a really easy solution. The solution is to override your Form's model class save() method manually.
class SomeUserClass extends myUser {
public function save(Doctrine_Connection $conn = null)
{
$this->setFirstName(trim($this->getFirstName()));
if($this->getFirstName())
{
return parent::save();
}else
{
return null;
}
}
}
In this example, I'm checking if the firstname field is blank. If its not, then save the form. If its empty, then we don't call save on the form.
I haven't been able to get the validators to work properly, and this is an equally clean solution.
Symfony gives you a bunch of hooks into the form/object saving process.
You can overwrite the blank values with null pre/post validation using by overriding the the doSave() or processValues() functions of the form.
You can read more about it here: http://www.symfony-project.org/more-with-symfony/1_4/en/06-Advanced-Forms#chapter_06_saving_object_forms
I'm building an app for the company I work for in symfony, non the less the app might be pretty useful outside our company so we decided to write it in a more general form so we can make it multi company. I'm facing a problem on how to define a default value for a field that is going to be in every single model (company_id) so we don't need to select which company we belong to every time we want to add data. can anyone help me?
I've tried
class TestForm extends BaseTestForm
{
function configure()
{
$this->setDefault('company_id', '1');
}
}
and when I submit the form I get a missing value for model ....
I did it, in the action of course, before the processForm and after the $this->form = new TestForm();
I used:
public function executeCreate(sfWebRequest $request)
{
...
$this->form->getObject()->setCompanyId('1');
...
}