howto handle edit forms with FileType inputs in sy

2020-05-24 22:20发布

问题:

in a symfony2 application a entity Message has a one-to-many relation to documents. Documents represents user uploads. i created a form. I realized two Forms: MessageForm and DocumentForm. DocumentForm lives inside a collection FormField in MessageForm. Uploading and processing files does work.

But if i want to edit the entity Message the Form contains as many empty FileInputs as there are Documents existing. desired behaviour would be:

  • FileInputs to upload new files
  • Filename (link) to existing files
  • Possibility to delete existing files

This should be handled inside the form. Changes should be done when the form is submitted.

How can this be realized?

回答1:

Solution is to write a custom form type extension. as described on http://symfony.com/doc/2.1/cookbook/form/create_form_type_extension.html.

filetype extension

    <?php

    use Symfony\Component\Form\AbstractTypeExtension;
    use Symfony\Component\Form\FormView;
    use Symfony\Component\Form\FormInterface;
    use Symfony\Component\Form\Util\PropertyPath;
    use Symfony\Component\OptionsResolver\OptionsResolverInterface;

    /**
     * Class FileTypeExtension
     *
     * @see http://symfony.com/doc/2.1/cookbook/form/create_form_type_extension.html
     */
    class FileTypeExtension extends AbstractTypeExtension
    {
        /**
        * Returns the name of the type being extended.
        *
        * @return string The name of the type being extended
        */
        public function getExtendedType()
        {
            return 'file';
        }

        /**
         * Add the image_path option
         *
         * @param OptionsResolverInterface $resolver
         */
        public function setDefaultOptions(OptionsResolverInterface $resolver)
        {
            $resolver->setOptional(array('file_path', 'file_name'));
        }

        /**
         * Pass the image url to the view
         *
         * @param FormView $view
         * @param FormInterface $form
         * @param array $options
         */
        public function buildView(FormView $view, FormInterface $form, array $options)
        {
            if (array_key_exists('file_path', $options)) {
                $parentData = $form->getParent()->getData();

                if (null !== $parentData) {
                    $propertyPath = new PropertyPath($options['file_path']);
                    $fileUrl = $propertyPath->getValue($parentData);
                } else {
                    $fileUrl = null;
                }

                $view->set('file_url', $fileUrl);
            }

            if (array_key_exists('file_name', $options)) {
                $parentData = $form->getParent()->getData();

                if (null !== $parentData) {
                    $propertyPath = new PropertyPath($options['file_name']);
                    $fileName = $propertyPath->getValue($parentData);
                } else {
                    $fileName = null;
                }

                $view->set('file_name', $fileName);
            }
        }
    }

customized file_widget

    {% block file_widget %}
        {% spaceless %}

            {% if file_url is not null %}
                <div><a href="{{ file_url }}">{{ file_name }}</a></div>
                <div style="display:none">{{ block('form_widget') }}</div>
            {% else %}
                {{ block('form_widget') }}
            {% endif %}

        {% endspaceless %}
    {% endblock %}

services.yml

    parameters:
        foobar.file_type_extension.class: Foobar\Form\Extension\FileTypeExtension

    services:
        foobar.file_type_extension:
            class: %replacethis.file_type_extension.class%
            tags:
              - { name: form.type_extension, alias: file }

inside a formtype

    $builder->add('file','file', array(
                "label" => "Datei",
                "required" => true,
                "attr" => array(),
                "file_path" => "webPath",
                "file_name" => "name"
            ));

that's it ;)



回答2:

In addition to the above answere - wich will let you build a file input wich can be rendered as a link (if it has an url) or a field (if it doesn't) - you might take a look at

http://symfony.com/doc/2.0/cookbook/form/form_collections.html

Wich in conjunction with some jQuery will let you add fields in UI.