I am building form with multiple image upload and I can't find solution for problem that is mentioned in title. To help me with that I included VichUploaderBundle
Right now I am stuck with this error and I can't find why and where is mistake in code:
Could not load type "file"
500 Internal Server Error - InvalidArgumentException
Does someone knows where is the problem?
Here is code that I am using:
ProductType class:
<?php
namespace AppBundle\Form\Type;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Form\Extension\Core\Type\CollectionType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Vich\UploaderBundle\Form\Type\VichFileType;
use AppBundle\Entity\Product;
class ProductType extends AbstractType
{
/**
* {@inheritdoc}
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('title', TextType::class)
->add('content', TextType::class)
->add('price', TextType::class)
->add('categories')
->add('productCondition')
->add("images", CollectionType::class, array(
'entry_type' => ProductImageType::class,
'allow_add' => true,
'allow_delete' => true
)
);
}
/**
* {@inheritdoc}
*/
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'data_class' => Product::class
));
}
}
ProductImageType class
<?php
namespace AppBundle\Form\Type;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
use Symfony\Component\Form\Extension\Core\Type\TextType;
class ProductImageType extends AbstractType
{
/**
* @param FormBuilderInterface $builder
* @param array $options
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('image', 'file')
;
}
/**
* @param OptionsResolverInterface $resolver
*/
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'data_class' => ProductImage::class
));
}
/**
* @return string
*/
public function getName()
{
return 'product_image';
}
}
services.yml
# Learn more about services, parameters and containers at
# http://symfony.com/doc/current/service_container.html
parameters:
# parameter_name: value
services:
# service_name:
# class: AppBundle\Directory\ClassName
# arguments: ["@another_service_name", "plain_value", "%parameter_name%"]
app.form.type.file:
class: AppBundle\Form\Type\ProductImageType
tags:
- { name: form.type }
EDIT:
I removed 'file' from ProductImageType and error is gone but Twig fails to render a form. Also I tried to use self::class instead of 'file' and that didn't helped either.
//ProductImageType class
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('image')
;
}
Results in Twig template:
<div class="form-group">
<label class="control-label required">Images</label>
<div id="product_images" data-prototype="<div class="form-group"><label class="control-label required">__name__label__</label><div id="product_images___name__"><div class="form-group"><label class="control-label required" for="product_images___name___image">Image</label><input type="text" id="product_images___name___image" name="product[images][__name__][image]" required="required" class="form-control" /></div></div></div>"></div>
</div>
EDIT 2: added Twig form
{% extends 'AppBundle::layout.html.twig' %}
{% block stylesheets %}
{{ parent() }}
<link href="{{ asset('/assets/vendor/components-font-awesome/css/font-awesome.min.css') }}" rel="stylesheet">
<link href="{{ asset('assets/css/form-elements.css') }}" rel="stylesheet">
<link href="{{ asset('assets/css/forms.css') }}" rel="stylesheet">
{% endblock %}
{% block content %}
<div class="top-content">
<div class="inner-bg">
<div class="container">
<div class="row">
<div class="col-md-6 col-md-offset-3">
<div class="form-box">
<div class="form-top">
<div class="form-top-left">
<h3>Create new product condition!</h3>
</div>
<div class="form-top-right">
<i class="fa fa-plus"></i>
</div>
</div>
<div class="form-bottom">
{{ form_start(form, { 'attr': {'class': 'product-form'} }) }}
{% spaceless %}
{% if not form.vars.valid %}
<div class="alert alert-error">
{{ form_errors(form) }}
{% for children in form.children %}
{% if not children.vars.valid %}
{{ form_errors(children) }}
{# or with field label
<ul>
{% for error in children.vars.errors %}
<li><b>{{ children.vars.label }}</b>: {{ error.message }}</li>
{% endfor %}
</ul>
#}
{% endif %}
{% endfor %}
</div>
{% endif %}
{% endspaceless %}
{{ form_row(form.title) }}
{{ form_row(form.content) }}
{{ form_row(form.price) }}
{{ form_row(form.categories) }}
{{ form_row(form.productCondition) }}
{{ form_row(form.images) }}
<button type="submit" class="btn">Submit!</button>
{{ form_end(form) }}
</div>
</div>
</div>
</div>
{% endblock content %}