I'm making an API with Symfony 4 and I'm trying to get it to accept a date, but it keeps throwing the Unable to transform data for property path "dateofbirth": Expected a string. error.
Field in entity:
/**
* #ORM\Column(type="date", nullable=true)
*/
private $dateofbirth;
Field in Form:
->add('dateofbirth', DateType::class, [
'html5' => false,
'required' => false,
'input' => 'string',
'input_format' => 'Y-m-d'
])
Now if I send it JSON with "dateofbirth": "1990-02-12" for example, it throws that error. I've also tried sending something like "dateofbirth": "1990-02-12T00:00:00+01:00" with the 'input_format' set to Y-m-d\TH:i:sP, but I get the same issue.
I've been messing around with the options array for a while now and I've also tried configurations other than the one above, but that's what I have right now. Instead of listing all the ones I've tried that didn't work, I hope someone can just tell me what does.
As per the DateType documentation:
input
The format of the input data - i.e. the format that the date is stored
on your underlying object.
Since you have declared your entity as #Column(type="date") you should set input to datetime. Symfony will create the object according to the input_format and map it to the model.
And since you are sending a single field, set widget to single_text, as the default value of choice will expect an object with day, month, year.
Related
I am developing a CMS using Sonata and Symfony 3.
I have used the JavaScript AutoNumeric library to force a numeric field to contain commas, in an effort to make the app more user-friendly.
The problem is that now when I try to save a record, the server flags the field with a "this value is not valid" message. Here is the annotation I am using on the field:
/**
* #var float
*
* #ORM\Column(name="amount", type="decimal", scale=2, precision=12, nullable=true)
* #Assert\NotNull(message = "validator.not_blank")
* #Assert\Range(
* min = 0,
* max = 9999999999
* )
*/
Is there a way to tell my server-side validator to strip out commas before validating?
===
Edit #1: This field is using the NumberType as its type. Here is the relevant admin code:
->add(
'amount',
NumberType::class,
array(
'label' => 'list.label.salary.amount',
'scale'=> 2,
'required' => true,
'attr' => array(
"class" => "compensation-number",
),
)
)
My JavaScript creates a new AutoNumeric instance with the form field as its input element.
Edit #2: In other words, this field is being treated as a string in the browser, and I need to convert that value into a float before it can be stored in the database. I'm not sure how best to do that.
I ended up duplicating the field in my Twig template, then using JavaScript to hide the "real" input. I then had a JavaScript listener update the "real" value with a cleaned-up version of the formatted number visible to users. That fixed my problem.
I am working on a Symfony 2.7 app that uses Sonata's admin bundle. I want to associate a Video with a Country, and I want to provide a default option if nothing is present. So I do this:
$formMapper
->tab('General')
->with('Editable', ['class' => 'col-md-6'])
->add('title')
->add(
'countryOfOrigin',
'country_of_origin',
[
'empty_data' => $user->getOriginCountry()
]
)
This works in that my record-creation screen gives me a nice form with my default value selected. But when I try to save my new record, I get this error:
Symfony\Component\Form\Exception\TransformationFailedException Unable
to reverse value for property path "countryOfOrigin": Expected a
string or null.
Any ideas on how to get around this error? I feel like I'm 90% to my destination.
We ended up punting on this for the moment by deciding not to have any default option. I would still be interested in hearing how others have solved this.
From https://docs.zendframework.com/zend-form/quick-start/#using-annotations:
Via using Zend\Form\Annotation, I can issue this directive:
/**
* #ComposedObject({
* "target_object":"Namespace\Model\ComposedCollection",
* "is_collection":"true",
* "options":{"count":2}
* });
*/
private $property;
What this does is create a collection of ComposedCollection elements, in the above case, of size 2.
It's great when I need a static form with 2 elements, but how do I change it when I want to alter it dynamically? i.e. internally I want to be able to populate the form with 4 or 5 sets of data, with the number being unknown ahead of time.
Using Annotations is static, and not dynamic. Is there any way to do this?
I have tried using
$form->get("element_name")->setOption("count", $numericValue);
but it does not work, because I am guessing by the time I am using it, the form has already been built by the Annotation engine ($annotationBuilder->createForm(MyEntity::class);
Is there a way to rebuild the form?
I have tried $form->prepare()
but it only actually removes my Collection elements instead.
I have also tried $form->init() but it appears to do nothing.
I am in the process of rewriting the form NOT using Annotations, but that's not what I am trying to accomplish, since I am effectively losing my Entity by rewriting it in a programmatic way.
Use Collection::setCount() method.
$form->get("element_name")->setCount($numericValue);
Also, as an alternative you can define fieldset programmatically. Place #Annotation\Exclude() on the $property and create a Fieldset like so:
$c = new Element\Collection('collection');
$c->setOptions([
'label' => 'Collection',
'count' => 1 ,
'should_create_template' => true,
'allow_add' => true,
'target_element' => [
'type' => ComposedCollectionFieldset::class
]
]);
Where ComposedCollectionFieldset contains the Elements that you need.
I'm using Symfony 2 and FOS User Bundle to create a website that handles user information.
I tried to create the edit page to change an existing profile.
My problem is that I want the birthdate to be an input text (because I'm using a Jquery Datapicker). It perfectly works on my register page but when I try to do the same for the profile/edit page, I have a 500 error saying "The form's view data is expected to be of type scalar, array or an instance of \ArrayAccess, but is an instance of class DateTime. You can avoid this error by setting the "data_class" option to "DateTime" or by adding a view transformer that transforms an instance of class DateTime to scalar, array or an instance of \ArrayAccess.".
Here is how I wrote my User (User.php entity) birthdate parameter:
/**
* #ORM\Column(name="birthdate", type="date")
* #Assert\NotBlank(groups={"Registration", "Profile"})
* #Assert\Date()
*/
protected $birthdate;
In my RegistrationFormType.php (that is working fine):
public function buildForm(FormBuilderInterface $builder, array $options)
{
...
$builder->add('givenname');
$builder->add('familyname');
$builder->add('birthdate', 'text');
...
}
When I try to copy paste this code, I got an error.
The only solution is to do the following:
$builder->add('birthdate', 'date', array('input' => 'datetime'));
This solution does work but is not what I want (it generates three select inputs, I would rather have a text input that uses my Jquery datepicker with my Jquery validation).
Do you have any idea why my error occurs on the edit page and not on the registration page?
Thank you!
I think you need to set the widget option of your date field to text. It's by default set to choice.
From the documentation:
text: renders a three field input of type text (month, day, year).
Example,
$builder->add('birthdate', 'date', array(
'input' => 'datetime',
'widget' => 'text'
));
You can also set it to single_text, which allows you to validate the user's input based on the format option.
Example,
$builder->add('birthdate', 'date', array(
'widget' => 'single_text',
// this is actually the default format for single_text
'format' => 'yyyy-MM-dd',
));
To let it work through a Date Picker, you've then to add the right class to your field.
How would I go about setting the default value of the datetime field of a form to the current time in Symfony2?
I'm using the FormBuilderInterface and the following isn't working:
$builder->add(
'completed_datetime', 'datetime', array('data' => new \DateTime('now'))
);
The form continues to show what I presume to be the default value for the datetime field 2008-01-01 00:00.
In the end it turned out I was viewing a cached version of my page. Ctrl+F5 cleared the cache and showed the desired result.
I was able to achieve the functionality I wanted in both the ways posted here, i.e.:
In the Type class:
$builder->add(
'completed_datetime', 'datetime', array('data' => new \DateTime('now'))
);
And in my controller:
$task->setCompletedDateTime(new \DateTime('now'));
I believe it's also possible to set it in my Task Entity class' constructor.