0

I have a Field class and a FieldType class associated to it and I want to create a interface where the user can edit the FieldType of all the Fields at once.

So I did the following:

protected function createUpdateForm() {     
    $fieldList = $this->getDoctrine()->getRepository('AppBundle:Field')->findAll();
    $fieldTypeList = $this->getDoctrine()->getRepository('AppBundle:FieldType')->findAll();

    $form = $this->createFormBuilder();
    foreach ($fieldList as $field){
        $form->add($field->getDescription(), ChoiceType::class,
                  ['choices' => $fieldTypeList, 
                   'choice_label' => 'getDescription', 
                   'multiple'=>false, 'expanded'=>true, 
                   'data' => $field->getFieldType()]);
    }       
    $form->add('action', SubmitType::class, ['label' => 'Update']);
    $form->add('cancel', SubmitType::class, ['label' => 'Cancel']);

    return $form->getForm();
}

It takes all the Fields from the database and creates a Radio group with the FieldTypes as the image shows (just the end of the form):

enter image description here

So for each Field the user can select the type and update the values. This is how I am updating the form, and that is what I do not like:

foreach ($form->getData() as $fieldType){
    $field = array_shift($fieldList);
    $field->setFieldType($fieldType);
    $em = $this->getDoctrine()->getManager();
    $em->flush();                   
}

It works, but everything look like a bodge, I do not like this. I'm starting with Symfony so I'm not sure, but there should be a better way to create the kind of form I need and persist it. I was trying to create a ColletionType, but it is not working out.

Does anybody know a better way to do this?

I have a more complex case that will use a similar logic so I'm trying to figure this out.

1 Answer 1

1

Not sure if I understood you completely, but if I did, this calls for an CollectionType as far as I can see it. Plus, if you set the underlying type to be EntityType you simplify the things even more.

I think something like this should work:

$fieldList = $this->getDoctrine()->getRepository('AppBundle:Field')->findAll();

$form = $this->createFormBuilder(['fields' => $fieldList])
    ->add('fields', CollectionType::class, [
        'entry_type' => EntityType::class,
        'entry_options' => [
            'class' => 'AppBundle:FieldType',
            'expanded' => true,
            'choice_label' => 'description'
        ]
    ])
    ->add('action', SubmitType::class, ['label' => 'Update'])
    ->add('cancel', SubmitType::class, ['label' => 'Cancel'])
    ->getForm();

Update:

{{ form_label(form.fields) }}
{% for f in form.fields %}
    {{ form_row(f, {'label': f.vars.value.description}) }}
{% endfor %}

Just bare in mind that I currently don't have dev env which I could use to check for typos, but it should work :)

Hope this helps a bit...

Sign up to request clarification or add additional context in comments.

3 Comments

Thanks for the reply! This is actually really close to what I need. It's almost working however I need a way to dynamically set the label of the entry_type as the description of the Field itself. In the image on my question, you can see that the bold text (website, social media) is the Field description. If I just use your code, the label end up as the Field id, but for that to happen I had to set the id property to public for some reason. Sorry if I'm being a bit demanding, but do you have any idea how to solve it?
Without creating your own type and form rendering customization, that could be tricky. This is because label in form type is of string type and does not accept callable. The update I added above could potentially help you, but it is not ideal.
It did not work: (Impossible to access an attribute ("description") on a string variable ("1")). The object does not seems to be accessible. Well I guess I'll take a look in creating my own type, but I'm not even sure whether it is a better solution or not, thanks anyway.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.