2015-09-03 3 views
2

Я имел эту работу ранее, но он перестал работать с Symfony 2,7 ​​Symfony 2,7 ​​Тип Форма Entity рендеринг нескольких свойств в виде

То, что я хочу, чтобы сделать расширенный/список выбора несколько сущностей, таких, что я отображения нескольких пользовательских свойства. Цель состоит в том, чтобы перечислить варианты, как:

{name} - {description} More info

Так что я создал пользовательский тип формы с «объектом», как родитель, чтобы я мог настроить форму рендеринга

<?php 
namespace Study\MainBundle\Form\Type; 

use Symfony\Component\Form\AbstractType; 
use Symfony\Component\Form\FormBuilderInterface; 
use Symfony\Component\Form\FormView; 
use Symfony\Component\Form\FormInterface; 
use Symfony\Component\OptionsResolver\OptionsResolver; 

class ScholarshipEntityType extends AbstractType 
{ 
    public function buildForm(FormBuilderInterface $builder, array $options) 
    { 
     $builder->setAttribute('dataType', $options['dataType']); 
    } 

    public function configureOptions(OptionsResolver $resolver) 
    { 
     $resolver->setDefaults(array(
      'required' => false, 
      'dataType' => 'entity' 
     )); 
    } 

    public function getAllowedOptionValues(array $options) 
    { 
     return array('required' => array(false)); 
    } 

    public function getParent() 
    { 
     return 'entity'; 
    } 

    public function getName() 
    { 
     return 'scholarship_entity'; 
    } 

} 

оказывает тип следующим образом (это было только на основе от шаблона расслоения Twitter Bootstrap):

{% block scholarship_entity_widget %} 
{% spaceless %} 
    {% if expanded %} 
     {% set label_attr = label_attr|merge({'class': (label_attr.class|default(''))}) %} 
     {% set label_attr = label_attr|merge({'class': (label_attr.class ~ ' ' ~ (widget_type != '' ? (multiple ? 'checkbox' : 'radio') ~ '-' ~ widget_type : ''))}) %} 
     {% if expanded %} 
      {% set attr = attr|merge({'class': attr.class|default(horizontal_input_wrapper_class)}) %} 
     {% endif %} 
     {% for child in form %} 
      {% if widget_type != 'inline' %} 
      <div class="{{ multiple ? 'checkbox' : 'radio' }}"> 
      {% endif %} 
       <label{% for attrname, attrvalue in label_attr %} {{ attrname }}="{{ attrvalue }}"{% endfor %}> 
        {{ form_widget(child, {'horizontal_label_class': horizontal_label_class, 'horizontal_input_wrapper_class': horizontal_input_wrapper_class, 'attr': {'class': attr.widget_class|default('')}}) }} 
        {{ child.vars.label.name|trans({}, translation_domain) }} 
        - {{ child.vars.label.description }} 
        <a href="{{ child.vars.label.link }}" target="_blank">More Information</a> 
       </label> 
      {% if widget_type != 'inline' %} 
      </div> 
      {% endif %} 
     {% endfor %} 
     {{ block('form_message') }} 
     {% if expanded %} 
     {% endif %} 
    {% else %} 
     {# not being used, just default #} 
     {{ block('choice_widget_collapsed') }} 
    {% endif %} 
{% endspaceless %} 
{% endblock %} 

Наконец, я использую свой собственный тип в другой форме:

public function buildForm(FormBuilderInterface $builder, array $options) 
{ 
    $builder 
     // ... 
     ->add('scholarships', new ScholarshipEntityType(), array(
      'class' => 'StudyMainBundle:Scholarship', 
      'query_builder' => function(EntityRepository $er) use ($options) { 
       return $er->findAllByOfferingQueryBuilder($options['offering']); 
      }, 
      'choice_label' => 'entity', 
      'multiple' => true, 
      'expanded' => true, 
      'label' => 'financial.scholarships' 
     )) 
    ; 
} 

«собственность» Я рендеринг только сам объект:

/** 
* Scholarship 
* 
* @ORM\Table(name="scholarship") 
* @ORM\Entity(repositoryClass="Study\MainBundle\Repository\ScholarshipRepository") 
*/ 
class Scholarship 
{ 
    /** 
    * @var integer 
    * 
    * @ORM\Column(name="id", type="integer") 
    * @ORM\Id 
    * @ORM\GeneratedValue(strategy="AUTO") 
    */ 
    private $id; 

    // ... 

    /** 
    * Get the Entity object for form rendering 
    * 
    * @return \Study\MainBundle\Entity\Scholarship 
    */ 
    public function getEntity() 
    { 
     return $this; 
    } 
} 

К сожалению, это выглядит как мой трюк, который не проходили весь Entity в Twig и выпускающий мне свойства доступа больше не работает , Есть некоторые изменения, в которых метка отображается как строка (я изменил свойство «на» на «choice_label» выше для 2.7, если это имеет значение).

Ошибка:

Catchable Fatal Error: Object of class Study\MainBundle\Entity\Scholarship could not be converted to string

Трассировка стека:

1. in vendor/symfony/symfony/src/Symfony/Component/Form/ChoiceList/Factory/DefaultChoiceListFactory.php at line 251 + 
2. at ErrorHandler ->handleError ('4096', 'Object of class Study\MainBundle\Entity\Scholarship could not be converted to string', '/var/project/vendor/symfony/symfony/src/Symfony/Component/Form/ChoiceList/Factory/DefaultChoiceListFactory.php', '251', array('choice' => object(Scholarship), 'key' => '0', 'label' => object(Closure), 'values' => array('2'), 'index' => array('Symfony\Bridge\Doctrine\Form\Type\DoctrineType', 'createChoiceName'), 'attr' => null, 'isPreferred' => array(), 'preferredViews' => array(), 'otherViews' => array(), 'value' => '2', 'nextIndex' => '2')) 
in vendor/symfony/symfony/src/Symfony/Component/Form/ChoiceList/Factory/DefaultChoiceListFactory.php at line 251 + 
3. at DefaultChoiceListFactory ::addChoiceView (object(Scholarship), '0', object(Closure), array('2'), array('Symfony\Bridge\Doctrine\Form\Type\DoctrineType', 'createChoiceName'), null, array(), array(), array()) 
in vendor/symfony/symfony/src/Symfony/Component/Form/ChoiceList/Factory/DefaultChoiceListFactory.php at line 185 

Есть еще один способ для достижения этой цели?

Я думал о следующем (но точно не знаю, как сделать это, или если это стоит посмотреть в любой из них):

  • трансформаторы
  • пользовательского типа, который является производным от выбора и делает то, что я хочу (возможно, из пучка)
  • с помощью списка выбора завода как-то
  • передавая объект как некоторое дополнительное поле вместо метки (может быть новый "choice_attr?)
+0

Поскольку поле выбора получило [сильно изменено в версии 2.7] (http://symfony.com/blog/new-in-symfony-2-7-choice-form-type-refactorization), попробуйте несколько других новые свойства. Может быть, '' choice_as_values ​​'=> true' будет делать трюк. – Yoshi

+0

Я только что закончил конвертировать все мои формы, чтобы сделать это. Это не помогло в этом случае (я не думаю, что это изменение по умолчанию для 2.7, но то, что будет по умолчанию в 3.0) – Matt

+1

В 2.5 можно было использовать метод 'buildView' типа поля для передачи произвольных данных к шаблону. – Joshua

ответ

2

Если я правильно понял проблему, вы должны реализовать функцию __toString() в вашей сущности, которая будет форматировать строку, которую вы хотите распечатать, в списке выбора для вашей сущности.

Например:

function __toString() { 
    return sprintf("%s - %s", $this->type, $this->description); 
} 
+0

Я также хочу показать ссылку внутри тега 'a' html. Но могу ли я просто сделать все это и установить метку для рендеринга без экранирования HTML? – Matt

+0

Это сложно ... В этом случае в функции '__toString()' вы можете использовать 'htmlentities ($ this-> name)' и 'htmlEntities ($ this-> description)', плюс ссылку (Inside ' '), затем используйте' | raw' ... – Dric512

+0

Я использовал 'htmlspecialchars' (вот что, по-видимому, делает Twig). Я также определил это как новый геттер, чтобы сохранить чистоту. В противном случае это решение сработало для меня. Мне не нравится перемещать код из Twig в Entity, но он работает. – Matt

0

Попробуйте использовать метод AbstractType::buildView(FormView, FormInterface, array). Там вы можете получить доступ к переменным, которые передаются в шаблон.

Я использовал его для DaterangeType объявить отдельные идентификаторы и имена для двух полех даты:

public function buildView(FormView $view, FormInterface $form, array $options) 
{ 
    $view->vars['full_name_0'] = $view->vars['full_name'] . '[0]'; 
    $view->vars['full_name_1'] = $view->vars['full_name'] . '[1]'; 

    $view->vars['id_0'] = $view->vars['id'] . '_0'; 
    $view->vars['id_1'] = $view->vars['id'] . '_1'; 
} 

Вы можете получить доступ к этим значению в качестве стандартного переменного прута.

+0

Это может помочь. Но если у меня есть тип «entity», то выбор автоматически связывается с Entities на основе запроса, который я запускаю. Есть ли способ сделать это по выбору в типе выбора объекта? – Matt

Смежные вопросы