Symfony 2.x Form Field Name - forms

When I render a form, form Filed Name is given as an array. For example: search[item], search[keyword] etc. where search is name of the form.
I'm not great on working with forms but I think, the name should be rendered as simply, name="item" or name="keyword".
I've looked at all the documentation, customizing form rendering topic etc. but I can't find any way to change the default behaviour of Symfony form to render form filed name from 'search[item]' to 'item'.
This way, when I ask for the POST data, I can ask simply $this->getRequest()->request->get('item'), as I have to deal with lots of individual parameters.
Help would be great i) To figure out how to achieve what I want. ii) to let me know, why the name is rendered this way. is this the good practice?

Rather than accessing parameters from the Request object, you can bind the Request object to the form.
For example, in your controller method that you post your form to:
namespace Acme\Controller;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Acme\Form\MyFormClass;
class MyFormController extends Controller
{
receiveFormAction(Request $request)
{
$form = new MyFormClass();
// you can specify that a route only accepts a post
// request in the routing definition
if ($request->isMethod('POST')) {
// this populates the form object with the data
// from the form submission
$form->bind($request);
if ( ! $form->isValid()) {
throw new \Exception('Invalid form');
}
// an array of the data the format you require
$data = $form->getData();
$data['item'];
$data['keyword'];
// etc.
}
}
}
The above is the way you should be handling forms in Symfony 2, and is how you can leverage the power that the forms component gives you, with validation etc.

Symfony supports multiple forms on a page. They might be instances of the same form or have similar field names. Having the fields for each form all together in an array makes this easy to do.

Related

symfony2 forms custom fields

So, I have a form for editing blog articles.
Among other things I need to be able to edit article tags. They are stored as ArrayCollection inside my Blog entity. (ManyToMany cascade: persist,remove)
Now, Simfony handles this type of data with <select> tag and it works just fine for selecting, but I want to be able to remove and add tags too.
This is also possible and is very well explained in this Cookbook article: How to Embed a Collection of Forms
However, result of this tutorial is still not very elegant and I would love to have input box similar to StackOverflow tag box.
Since there are many already done solutions under free licences I decided to just use one of them, for example jQuery Tags Input.
Basically, all I need to do is run $('#tags_input_box').tagsInput() and it transforms it into SO-like tag box.
Now, I'm searching for the easiest way to bind some custom made input to my form and submit it back together with the rest of 'genuine' fields in a shape that will be understood by Symfony2.
Could anyone refer me to some document or give me some starting info where I should begin my research on this matter ?
It appears that plugin sends it in as a comma-separated string value.
Probably the easiest way would be to simply treat it as a single input in your form, and then split it up when you process the form.
// Entity to hold it in string form.
namespace Some\Entity;
class TagStringEntity {
protected $tagString;
// getTagString and setTagString
}
// Custom form type.
// Use this AbstractType in your form.
namespace Some\Form;
Symfony\Component\Form\AbstractType;
class TagType extends AbstractType {
public buildForm(FormBuilder $builder, array $options) {
$builder->add('tagString'); // will default to text field.
}
}
// In Controller
public function displayFormAction() {
// Join the tags into a single string.
$tagString = implode(',', $article->getTags()); // assuming it returns an array of strings.
$tagStringType = new TagStringType();
$tagStringType->setTagString($tagString);
// build form, etc...
}
public function checkFormAction() {
// ...
if ($form->isValid()) {
// Get the tag string, split it, and manually create your separated tag objects to store.
}
}
That's probably the cleanest and simplest way to do it using that jQuery plugin. Takes a bit of working around since you are turning multiple items into many and vice versa, but not too bad.

Zend creating forms based on requests within one controller/action

I don't really know how to word the title well, but here's my issue. I decided instead of having 25 controllers to handle pages, I have one PageController with a viewAction that takes in a :page parameter - for example, http://localhost/website/page/about-us would direct to PageController::viewAction() with a parameter of page = about-us. All of the pages are stored in a templates folder, so the viewrenderer is set to render application\templates\default\about-us.phtml.
I did this so I can consolidate and it seemed like a better approach. My question is the following: lets say when the page request is contact-us, I would need a Zend_Form to be used within the contact page. So, I would need a way within PageController::viewAction() to recognize that the page needs to have a form built, build the form, and also upon submission the need to process it (maybe this should be handled in an abstract process method - not sure).
I have no idea how to implement this. I thought maybe I can store a column with the name of a form and a connecting page identifier. Even better, create a one-to-many page to forms, and then in the submission loop through the forms and check if submitted and if so then process it (maybe there is a isSubmitted() method within zend_form. I really don't know how to handle this, and am looking for any help i can get.
Thanks!
Here is something that came to mind that may work or help point you in a direction that works for you.
This may only work well assuming you were to have no more than one form per page, if you need more than one form on a page, you would have to do something beyond this automatic form handling.
Create a standard location for forms that are attached to pages (e.g. application/forms/page). This is where the automatic forms associated with pages will be kept.
In your viewAction, you could take advantage of the autoloader to see if a form for that page exists. For example:
$page = $this->getParam('page');
$page = ucfirst(preg_replace('/-(\w)/ie', "strtoupper('$1')", $page)); // contact-us -> ContactUs
$class = 'Application_Form_Page_' . $page;
// class_exists will invoke the autoloader to map a class to a file
if (class_exists($class)) {
// a form is defined for this page
$form = new $class();
// check if form was posted
if ($this->getRequest()->isPost()) {
if ($form->isValid($this->getRequest()->getPost()) {
// form is valid - determine how to process it
}
}
// assign the form to the view
$this->view->pageForm = $form;
}
All this really leaves out is the action you take to process a specific form. Since the contact form will likely generate an email, and another form may insert data into a database, you will need some sort of callback system or perhaps another class that can be mapped automatically which contains the form processor code.
Anyway something along those lines is what came to mind first, I hope that helps give you some more ideas.

How can I use the sfValidatorEmail validator in Symfony to validate a single email field

I have a form with 2 elements that will be submitted and then update part of a user profile.
I don't want to use the entire generated form and have to remove all the fields except for the two I need. I just want to be able to create a quite simple form to do my update.
Is there a way to utilize Symfony's sfValidatorEmail inside the action on the returned value of an email field?
Since the regex is already written in the validator, I would like to reuse it, but I don't know how to use it in the action after the non-symfony form has been submitted.
Two approaches here - you could construct a simple form anyway extending from sfForm/sfFormSymfony (doesn't have to be ORM-based) that just contains the 2 fields you want. That way you can use the existing validation framework, and then use $myForm->getValues() after everything has been validated to get your values for your profile update.
Alternatively, as you've mentioned, you can use the sfValidatorEmail class in your action like so:
$dirtyValue = "broken.email.address"
$v = new sfValidatorEmail();
try
{
$v->clean($dirtyValue);
}
catch (sfValidatorError $e)
{
// Validation failed
}
The latter approach quickly leads to messy code if you have many values that need cleaning, and it's worth putting the logic back into a form to handle this in the usual manner.
If you're submitting a form with 2 elements, it should be a form on the edit and update end, period. Symfony forms are lightweight, there's no performance reason to not use them. Instead, make a custom form for this purpose:
class ProfileUpdateForm extends ProfileForm
{
public function configure()
{
$this->useFields(array('email', 'other_field'));
}
}

Symfony forms or normal HTML forms

I am using Symfony 1.4 to create project, and i need to create dynamic forms depending upon the question set type coming from database. i have used Symfony forms in rest of my project, but in this case using symfony forms seems to be tough, as i need dynamic form.
can it be safe to use normal HTML forms..in symfony project, or it is advisable to use Symfony forms. so need your help.
You can use html forms, but it would bypass symfony's form validation system.
You can still build dynamic forms by creating and adding input widgets to the current form, or a new form inside an action. You can then echo the form in the template and the dynamically generated fields will be part of the form as well.
If you start with a MyForm.class.php in the lib/forms, make sure to add:
$this->validatorSchema->setOption('allow_extra_fields', true);
Otherwise, you will automatically get validation errors. If you want to add fields to a form in an action you would do something like this:
$this->form = new MyForm();
$widgetSchema = $this->form->getWidgetSchema();
$widgetSchema['add_field'] = new sfWidgetFormInputText();
When you echo your form the 'add_field' input will be added to it.
It would help to have more information about what you're doing, but here's one way in which forms can be dynamic in Symfony. This code creates widgets and validators for a survey dynamically based on the "type" of a question:
class SurveyAnswerForm extends BaseSurveyAnswerForm
{
public function configure()
{
$question = $this->object->Question;
$method = sprintf('createWidgetAndValidatorFor%sInputType', $question->type);
$this->$method($question);
$this->getWidget('value')->setOption('label', $question->question);
$this->getValidator('value')->setOption('required', $question->required);
}
protected function createWidgetAndValidatorForTextFieldInputType(Question $question)
{
$this->setWidget('value', new sfWidgetFormInputText());
$this->setValidator('value', new sfValidatorString());
}
protected function createWidgetAndValidatorForTextAreaInputType(Question $question)
{
$this->setWidget('value', new wfWidgetFormTextareaAutosize());
$this->setValidator('value', new sfValidatorString());
}
//etc. for as many types as you require
}
Note: while this answer is code from one of my projects, it was heavily influenced by this answer over on SymfonyExperts.

JQuery validation based on class?

I have a form that will have dynamically created elements, one of those will be of date type. There can also be many fields of this type on my form, all which must be validated.
I am using a strongly typed view in Asp MVC, so the name will change based on various factors. What I would like to do is validate based on a class name instead, since that will be constant for that type of field.
Ie:
<%= Html.TextBox("questionAnswers[" + index + "].AnswerValue", qa.AnswerValue, new { #class = "DateTypeClass" })%>
So then I would need JQuery validation based on the classname DateTypeClass versus the Name.
Any ideas?
In your validation function you could check the value like so:
var dateFieldValue = $(".DateTypeClass").val();
//validate dateFieldValue here
Also you don't have to resort to selecting by class if you don't want to. If no other fields share this validation then you could select by partial id in jquery. That would look like this:
var dateFieldValue = $("[id^=someId]").val();
//validate dateFieldValue here
So you would if set someId on the field and ASP.Net adds some additional stuff to the id it will still select it properly. I don't use ASP.Net MVC so not sure where you are setting the ID (if at all)
Also if you want inline validation you can wireup the onBlur event like so:
$(".DateTypeClass").blur(function(){
//Call field validation function here
});