Чи існує простий спосіб встановити значення за замовчуванням для поля текстової форми?
Чи існує простий спосіб встановити значення за замовчуванням для поля текстової форми?
Відповіді:
Можна легко використовувати під час створення із:
->add('myfield', 'text', array(
'label' => 'Field',
'empty_data' => 'Default value'
))
'data'
ключ на'value'
empty_data
data
марний - він перезаписує збережене значення. empty_data
не показує значення, воно використовує його при надсиланні порожнього значення і унеможливлює збереження неперевірених варіантів.
ви можете встановити значення за замовчуванням за допомогою empty_data
$builder->add('myField', 'number', ['empty_data' => 'Default value'])
Я думав про це кілька разів у минулому, тому думав, що я сформулюю різні ідеї, які мав / використовував. Щось може бути корисним, але жодне не є "ідеальним" рішенням Symfony2.
Конструктор В Entity ви можете зробити $ this-> setBar ('значення за замовчуванням'); але це називається кожен раз, коли ви завантажуєте сутність (db чи ні) і трохи заплутано. Однак це працює для кожного типу поля, оскільки ви можете створювати дати або все, що вам потрібно.
Якщо твердження в get отримати я не став би, але ви могли.
return ( ! $this->hasFoo() ) ? 'default' : $this->foo;
Фабрика / екземпляр . Викличте статичну функцію / вторинний клас, який надає вам об'єкт за замовчуванням, попередньо заповнений даними. Напр
function getFactory() {
$obj = new static();
$obj->setBar('foo');
$obj->setFoo('bar');
return $obj;
}
Не дуже ідеально, зважаючи на те, що вам доведеться підтримувати цю функцію, якщо ви додаєте додаткові поля, але це означає, що ви відокремлюєте набір даних / типовий і той, що генерується з db. Так само ви можете мати декілька getFactories, якщо вам потрібні різні дані за замовчуванням.
Розширені / Відображаючі об'єкти Створіть об'єкт, що розширюється (наприклад, FooCreate розширює Foo), який дає вам дані про дефолт під час створення (через конструктор). Подібно до фабричної / екземплярної ідеї просто інший підхід - я віддаю перевагу статичним методам особисто.
Встановлення даних перед формою збірки У конструкторах / службі ви знаєте, чи є у вас новий об'єкт чи він був заповнений з db. Тому правдоподібно викликати набір даних у різних полях, коли ви захоплюєте нову сутність. Напр
if( ! $entity->isFromDB() ) {
$entity->setBar('default');
$entity->setDate( date('Y-m-d');
...
}
$form = $this->createForm(...)
Події форми При створенні форми ви встановлюєте дані за замовчуванням під час створення полів. Ви користуєтеся цим використанням слухача подій PreSetData. Проблема з цим полягає в тому, що ви дублюєте код завантаження / дублювання коду форми і ускладнюєте їх підтримку / розуміння.
Розширені форми, подібні до подій форми, але ви називаєте різного типу залежно від того, чи є це db / new сутність. Під цим я маю на увазі, що у вас є FooType, який визначає вашу форму редагування, BarType розширює FooType це і встановлює всі дані на поля. Потім у своєму контролері ви просто вибираєте, який тип форми запровадити. Це гарно, якщо у вас є власна тема, хоча і, як події, створює занадто багато обслуговування для мого вподобання.
Twig Ви можете створити власну тему та за замовчуванням даних, використовуючи також значення параметра, коли ви робите це на основі поля. Ніщо не заважає вам перетворити це в тему форми, або якщо ви хочете зберегти шаблони чистими, а форму можна використовувати повторно. напр
form_widget(form.foo, {attr: { value : default } });
JS Було б тривіально заповнити форму функцією JS, якщо поля порожні. Ви можете щось зробити, наприклад, із заповнювачами. Це все-таки погана, погана ідея.
Форми як послуга Для одного з великих проектів на основі форм, які я зробив, я створив службу, яка генерувала всі форми, проводила всю обробку і т. Д. Це було тому, що форми повинні використовуватися в декількох контролерах в декількох середовищах і в той час як форми генерували / обробляли однаково, вони відображалися / взаємоділи з різними (наприклад, обробка помилок, перенаправлення тощо). Краса такого підходу полягала в тому, що ви можете налаштовувати дані за замовчуванням, робити все необхідне, обробляти помилки загально тощо, і все це інкапсульовано в одному місці.
Висновок Як я бачу, ви знову і знову будете стикатися з тим самим питанням - де жити дані про дефолт?
З цією метою я щоразу підходив до проблеми по-різному. Наприклад, параметр форми реєстрації "бюлетень" легко (і логічно) встановлюється в конструкторі безпосередньо перед створенням форми. Коли я створював колекції форм, які були пов'язані між собою (наприклад, які перемикачі в різних типах форм пов’язані між собою), то я використовував слухачів подій. Коли я створив складнішу сутність (наприклад, таку, яка вимагає дітей або багато даних про дефолт), я використовував функцію (наприклад, 'getFactory'), щоб створити її елемент, як мені це потрібно.
Я не думаю, що існує один "правильний" підхід, оскільки кожен раз, коли у мене була ця вимога, вона була дещо іншою.
Удачі! Я сподіваюся, що я дав тобі трохи їжі для роздумів і не надто сильно пом'ятав;)
Якщо вам потрібно встановити значення за замовчуванням, і ваша форма стосується сутності, слід скористатися наступним підходом:
// buildForm() method
public function buildForm(FormBuilderInterface $builder, array $options) {
$builder
...
->add(
'myField',
'text',
array(
'data' => isset($options['data']) ? $options['data']->getMyField() : 'my default value'
)
);
}
В іншому випадку myField
завжди буде встановлено значення за замовчуванням, замість отримання значення від сутності.
$options['data']->getMyField()
на$option['data']['myField']
empty_data
: Цей параметр визначає, яке значення поверне поле, коли подане значення буде порожнім. Він не встановлює початкового значення
Ви можете встановити за замовчуванням для відповідного поля у вашому класі моделей (у визначенні відображення або встановити значення самостійно).
Крім того, FormBuilder дає можливість встановити початкові значення методом setData () . Конструктор форм передається методу createForm () вашого класу форм.
Також перевірте це посилання: http://symfony.com/doc/current/book/forms.html#using-a-form-without-a-class
Якщо ваша форма пов'язана з сутністю, просто встановіть значення за замовчуванням для самої сутності за допомогою методу конструювання:
public function __construct()
{
$this->field = 'default value';
}
'mapped' => false
). Використовуйте setData(...)
для цього.
Підхід 1 (від http://www.cranespud.com/blog/dead-simple-default-values-on-symfony2-forms/ )
Просто встановіть значення за замовчуванням у вашій сутності, або в декларації змінної, або в конструкторі:
class Entity {
private $color = '#0000FF';
...
}
або
class Entity {
private $color;
public function __construct(){
$this->color = '#0000FF';
...
}
...
}
Підхід 2 з коментаря у вищенаведеному посиланні, а також відповідь Дмитра (не прийнята) із розділу Як встановити значення за замовчуванням для поля форми в Symfony2?
Додайте значення за замовчуванням до атрибуту даних при додаванні поля за допомогою FormBuilder, адаптованого з відповіді Дмитра.
Зауважте, що це передбачає, що властивість буде і матиме значення null лише тоді, коли це нове, а не існуюче, сутність.
public function buildForm(FormBuilderInterface $builder, array $options) {
$builder->add('color', 'text', array(
'label' => 'Color:',
'data' => (isset($options['data']) && $options['data']->getColor() !== null) ? $options['data']->getColor() : '#0000FF'
)
);
}
Ви можете встановити значення за замовчуванням, наприклад, для такої форми message
:
$defaultData = array('message' => 'Type your message here');
$form = $this->createFormBuilder($defaultData)
->add('name', 'text')
->add('email', 'email')
->add('message', 'textarea')
->add('send', 'submit')
->getForm();
У випадку, якщо ваша форма відображена в об'єкті, ви можете перейти так (наприклад, ім'я користувача за замовчуванням):
$user = new User();
$user->setUsername('John Doe');
$form = $this->createFormBuilder($user)
->add('username')
->getForm();
Загальне рішення для будь-якого випадку / підходу, головним чином, за допомогою форми без класу або коли нам потрібен доступ до будь-яких служб для встановлення значення за замовчуванням:
// src/Form/Extension/DefaultFormTypeExtension.php
class DefaultFormTypeExtension extends AbstractTypeExtension
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
if (null !== $options['default']) {
$builder->addEventListener(
FormEvents::PRE_SET_DATA,
function (FormEvent $event) use ($options) {
if (null === $event->getData()) {
$event->setData($options['default']);
}
}
);
}
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefault('default', null);
}
public function getExtendedType()
{
return FormType::class;
}
}
і зареєструйте розширення форми:
app.form_type_extension:
class: App\Form\Extension\DefaultFormTypeExtension
tags:
- { name: form.type_extension, extended_type: Symfony\Component\Form\Extension\Core\Type\FormType }
Після цього ми можемо використовувати default
опцію в будь-якому полі форми:
$formBuilder->add('user', null, array('default' => $this->getUser()));
$formBuilder->add('foo', null, array('default' => 'bar'));
Не використовувати:
'data' => 'Default value'
Читайте тут: https://symfony.com/doc/current/reference/forms/types/form.html#data
"Опція даних завжди переосмислює значення, взяте з даних домену (об'єкта) під час надання. Це означає, що значення об'єкта також перевизначається, коли форма редагує вже збережений об'єкт, внаслідок чого він втрачає збережене значення під час подання форми."
Використовуйте наступне:
Скажімо, для цього прикладу у вас є Entity Foo, і є поле "активне" (у цьому прикладі є CheckBoxType, але процес такий же, як і для всіх інших типів), яке ви хочете перевірити за замовчуванням
У ваш клас FooFormType додайте:
...
use Symfony\Component\Form\FormEvent;
use Symfony\Component\Form\FormEvents;
...
public function buildForm( FormBuilderInterface $builder, array $options )
{
...
$builder->add('active', CheckboxType::class, array(
'label' => 'Active',
));
$builder->addEventListener(
FormEvents::PRE_SET_DATA,
function(FormEvent $event){
$foo = $event->getData();
// Set Active to true (checked) if form is "create new" ($foo->active = null)
if(is_null($foo->getActive())) $foo->setActive(true);
}
);
}
public function configureOptions( OptionsResolver $resolver )
{
$resolver->setDefaults(array(
'data_class' => 'AppBundle:Foo',
));
}
'data' => $data['myfield'] ?? 'Default value'
->addEventListener(FormEvents::PRE_SET_DATA, function (FormEvent $event) {
$form = $event->getForm();
$data = $event->getData();
if ($data == null) {
$form->add('position', IntegerType::class, array('data' => 0));
}
});
$event->setData()
замість читання поля може зробити це ще краще.
Просто так я розумію проблему.
Ви хочете скорегувати спосіб побудови форми на основі даних у вашій сутності. Якщо сутність створюється, використовуйте якесь значення за замовчуванням. Якщо сутність існує, використовуйте значення бази даних.
Особисто я думаю, що рішення @ MolecularMans - це шлях. Я б фактично встановив значення за замовчуванням в конструкторі або в операторі властивості. Але вам, здається, такий підхід не подобається.
Натомість ви можете слідувати цьому: http://symfony.com/doc/current/cookbook/form/dynamic_form_modification.html
Ви повісите слухача на тип вашої форми, а потім зможете вивчити свою сутність та відкоригувати програму-> відповідно додати заяви на основі havine нової чи існуючої сутності. Вам все ще потрібно десь вказати значення за замовчуванням, хоча ви можете просто кодувати їх у своєму слухачі. Або передати їх у тип форми.
Схоже, багато роботи, хоча. Краще просто передати об'єкт у форму із уже встановленими значеннями за замовчуванням.
Часто для init значень за замовчуванням форми я використовую світильники. Зрозуміло, цей спосіб не найпростіший, але дуже зручний.
Приклад:
class LoadSurgeonPlanData implements FixtureInterface
{
public function load(ObjectManager $manager)
{
$surgeonPlan = new SurgeonPlan();
$surgeonPlan->setName('Free trial');
$surgeonPlan->setPrice(0);
$surgeonPlan->setDelayWorkHours(0);
$surgeonPlan->setSlug('free');
$manager->persist($surgeonPlan);
$manager->flush();
}
}
Тим не менш, поле типу Symfony має параметри даних .
Приклад
$builder->add('token', 'hidden', array(
'data' => 'abcdef',
));
Є дуже простий спосіб, ви можете встановити типові параметри, як тут:
$defaults = array('sortby' => $sortby,'category' => $category,'page' => 1);
$form = $this->formfactory->createBuilder('form', $defaults)
->add('sortby','choice')
->add('category','choice')
->add('page','hidden')
->getForm();
Якщо ви встановите "дані" у формі створення, це значення не змінюватиметься під час редагування вашої сутності.
Моє рішення:
public function buildForm(FormBuilderInterface $builder, array $options) {
// In my example, data is an associated array
$data = $builder->getData();
$builder->add('myfield', 'text', array(
'label' => 'Field',
'data' => array_key_exits('myfield', $data) ? $data['myfield'] : 'Default value',
));
}
До побачення.
'data' => $data['myfield'] ?? 'Default value',
Значення за замовчуванням встановлюються, налаштовуючи відповідну сутність. Перш ніж прив’язувати об'єкт до форми, встановіть його поле кольору на "# 0000FF":
// controller action
$project = new Project();
$project->setColor('#0000FF');
$form = $this->createForm(new ProjectType(), $project);
Якщо це поле пов'язане з сутністю (є властивістю цієї сутності), ви можете просто встановити для нього значення за замовчуванням.
Приклад:
public function getMyField() {
if (is_null($this->MyField)) {
$this->setMyField('my default value');
}
return $this->MyField;
}
Зазвичай я просто встановлюю значення за замовчуванням для конкретного поля моєї сутності:
/**
* @var int
* @ORM\Column(type="integer", nullable=true)
*/
protected $development_time = 0;
Це буде працювати для нових записів або просто оновлення існуючих.
'empty_data'
використовується зворотний виклик, щоб дозволити параметри конструктора на об'єкті.
Коли Брайан запитав:
Здається, що порожні_дані встановлюють поле лише 1, коли воно подано без значення. Що робити, коли ви хочете, щоб форма за замовчуванням відображала значення 1 на вході, коли значення немає?
ви можете встановити значення за замовчуванням за допомогою empty_value
$builder->add('myField', 'number', ['empty_value' => 'Default value'])