Apakah ada cara mudah untuk menetapkan nilai default untuk bidang formulir teks?
Apakah ada cara mudah untuk menetapkan nilai default untuk bidang formulir teks?
Jawaban:
Dapat digunakan selama pembuatan dengan mudah dengan:
->add('myfield', 'text', array(
'label' => 'Field',
'empty_data' => 'Default value'
))
'data'
kunci untuk'value'
empty_data
data
tidak berguna - itu menimpa nilai yang disimpan. empty_data
tidak menunjukkan nilainya, ia menggunakannya pada nilai kosong yang dikirimkan dan membuatnya tidak mungkin untuk menyimpan pilihan yang tidak dicentang.
Anda dapat mengatur nilai default dengan empty_data
$builder->add('myField', 'number', ['empty_data' => 'Default value'])
Saya telah merenungkan ini beberapa kali di masa lalu jadi saya pikir saya akan menuliskan berbagai ide yang saya miliki / gunakan. Sesuatu mungkin berguna, tetapi tidak ada solusi Symfony2 "sempurna".
Konstruktor Dalam Entitas Anda dapat melakukan $ this-> setBar ('nilai default'); tetapi ini disebut setiap kali Anda memuat entitas (db atau tidak) dan agak berantakan. Namun itu berfungsi untuk setiap jenis bidang karena Anda dapat membuat tanggal atau apa pun yang Anda butuhkan.
Jika pernyataan dalam get's saya tidak akan, tetapi Anda bisa.
return ( ! $this->hasFoo() ) ? 'default' : $this->foo;
Pabrik / contoh . Panggil fungsi statis / kelas sekunder yang memberi Anda Entitas default yang diisi sebelumnya dengan data. Misalnya
function getFactory() {
$obj = new static();
$obj->setBar('foo');
$obj->setFoo('bar');
return $obj;
}
Tidak terlalu ideal mengingat Anda harus mempertahankan fungsi ini jika Anda menambahkan bidang tambahan, tetapi itu berarti Anda memisahkan seter data / default dan apa yang dihasilkan dari db. Demikian pula Anda dapat memiliki beberapa getFactories jika Anda menginginkan data standar yang berbeda.
Entitas Extended / Refleksi Membuat Entitas yang diperluas (mis. FooCreate extends Foo) yang memberi Anda data default pada waktu pembuatan (melalui konstruktor). Mirip dengan ide Pabrik / contoh hanya pendekatan yang berbeda - Saya lebih suka metode statis secara pribadi.
Setel Data sebelum membangun formulir Di konstruktor / layanan, Anda tahu apakah Anda memiliki entitas baru atau jika itu diisi dari db. Oleh karena itu masuk akal untuk memanggil data yang diset pada bidang yang berbeda saat Anda mengambil entitas baru. Misalnya
if( ! $entity->isFromDB() ) {
$entity->setBar('default');
$entity->setDate( date('Y-m-d');
...
}
$form = $this->createForm(...)
Formulir Acara Saat Anda membuat formulir, Anda menetapkan data default saat membuat bidang. Anda menimpa ini menggunakan pendengar acara PreSetData. Masalah dengan ini adalah bahwa Anda menduplikasi formulir beban kerja / duplikasi kode dan membuatnya lebih sulit untuk dipertahankan / dipahami.
Formulir yang diperluas Mirip dengan Formulir acara, tetapi Anda memanggil jenis yang berbeda tergantung pada apakah itu db / entitas baru. Maksud saya, Anda memiliki FooType yang mendefinisikan formulir edit Anda, BarType memperluas FooType ini dan menyetel semua data ke bidang. Di controller Anda, Anda cukup memilih tipe formulir yang ingin dihasut. Ini menyebalkan jika Anda memiliki tema khusus dan suka acara, membuat terlalu banyak pemeliharaan sesuai dengan keinginan saya.
Ranting Anda dapat membuat tema Anda sendiri dan default data menggunakan opsi nilai juga ketika Anda melakukannya berdasarkan per-bidang. Tidak ada yang menghentikan Anda membungkus ini menjadi tema formulir baik Anda ingin menjaga template Anda bersih dan formulir dapat digunakan kembali. misalnya
form_widget(form.foo, {attr: { value : default } });
JS Akan sepele untuk mengisi formulir dengan fungsi JS jika bidang kosong. Anda dapat melakukan sesuatu dengan placeholder misalnya. Tapi ini ide yang buruk.
Formulir sebagai layanan Untuk salah satu proyek berbasis formulir besar yang saya lakukan, saya membuat layanan yang menghasilkan semua formulir, melakukan semua pemrosesan, dll. Ini karena formulir akan digunakan di beberapa pengontrol di beberapa lingkungan dan sementara formulir dihasilkan / ditangani dengan cara yang sama, mereka ditampilkan / berinteraksi dengan berbeda (misalnya penanganan kesalahan, pengalihan dll). Keindahan dari pendekatan ini adalah bahwa Anda dapat mengatur data secara default, melakukan semua yang Anda butuhkan, menangani kesalahan secara umum, dll, dan semuanya dienkapsulasi di satu tempat.
Kesimpulan Seperti yang saya lihat, Anda akan mengalami masalah yang sama berulang kali - di mana data default untuk hidup?
Untuk itu, saya sudah mendekati masalah secara berbeda setiap kali. Misalnya, opsi formulir "buletin" pendaftaran mudah (dan secara logis) disetel di konstruktor sebelum membuat formulir. Ketika saya sedang membangun koleksi formulir yang ditautkan bersama (mis. Tombol radio mana dalam berbagai jenis formulir ditautkan bersama) maka saya telah menggunakan Pendengar Acara. Ketika saya telah membangun entitas yang lebih rumit (misalnya entitas yang membutuhkan anak-anak atau banyak data yang gagal) saya telah menggunakan fungsi (misalnya 'getFactory') untuk membuat elemen itu sesuai kebutuhan saya.
Saya tidak berpikir ada satu pendekatan "benar" karena setiap kali saya memiliki persyaratan ini sudah sedikit berbeda.
Semoga berhasil! Saya harap saya telah memberi Anda beberapa makanan untuk dipikirkan dan tidak mengoceh terlalu banyak;)
Jika Anda perlu menetapkan nilai default dan formulir Anda terkait dengan entitas, maka Anda harus menggunakan pendekatan berikut:
// buildForm() method
public function buildForm(FormBuilderInterface $builder, array $options) {
$builder
...
->add(
'myField',
'text',
array(
'data' => isset($options['data']) ? $options['data']->getMyField() : 'my default value'
)
);
}
Jika tidak, myField
selalu akan ditetapkan ke nilai default, alih-alih mendapatkan nilai dari entitas.
$options['data']->getMyField()
dengan$option['data']['myField']
empty_data
: Opsi ini menentukan nilai apa yang akan dikembalikan bidang ketika nilai yang dikirimkan kosong. Itu tidak menetapkan nilai awal
Anda dapat mengatur default untuk bidang terkait di kelas model Anda (dalam pemetaan definisi atau mengatur sendiri nilainya).
Selanjutnya, FormBuilder memberi Anda kesempatan untuk mengatur nilai awal dengan metode setData () . Pembuat formulir diteruskan ke metode createForm () dari kelas formulir Anda.
Juga, periksa tautan ini: http://symfony.com/doc/current/book/forms.html#using-a-form-without-a-class
Jika formulir Anda terikat pada suatu entitas, cukup atur nilai default pada entitas itu sendiri menggunakan metode konstruk:
public function __construct()
{
$this->field = 'default value';
}
'mapped' => false
). Gunakan setData(...)
untuk ini.
Pendekatan 1 (dari http://www.cranespud.com/blog/dead-simple-default-values-on-symfony2-forms/ )
Cukup setel nilai default di entitas Anda, baik dalam deklarasi variabel atau konstruktor:
class Entity {
private $color = '#0000FF';
...
}
atau
class Entity {
private $color;
public function __construct(){
$this->color = '#0000FF';
...
}
...
}
Pendekatan 2 dari komentar di tautan di atas, dan juga jawaban Dmitriy (bukan yang diterima) dari Cara mengatur nilai default untuk bidang formulir di Symfony2?
Tambahkan nilai default ke atribut data saat menambahkan bidang dengan FormBuilder, diadaptasi dari jawaban Dmitriy.
Perhatikan bahwa ini mengasumsikan bahwa properti akan dan hanya akan memiliki nilai nol ketika itu adalah entitas yang baru, dan bukan yang sudah ada.
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'
)
);
}
Anda dapat menetapkan nilai default, misalnya untuk formulir message
, seperti ini:
$defaultData = array('message' => 'Type your message here');
$form = $this->createFormBuilder($defaultData)
->add('name', 'text')
->add('email', 'email')
->add('message', 'textarea')
->add('send', 'submit')
->getForm();
Jika formulir Anda dipetakan ke Entitas, Anda bisa seperti ini (mis. Nama pengguna default):
$user = new User();
$user->setUsername('John Doe');
$form = $this->createFormBuilder($user)
->add('username')
->getForm();
Solusi umum untuk setiap kasus / pendekatan, terutama dengan menggunakan formulir tanpa kelas atau ketika kita membutuhkan akses ke layanan apa pun untuk menetapkan nilai default:
// 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;
}
}
dan daftarkan ekstensi formulir:
app.form_type_extension:
class: App\Form\Extension\DefaultFormTypeExtension
tags:
- { name: form.type_extension, extended_type: Symfony\Component\Form\Extension\Core\Type\FormType }
Setelah itu, kita dapat menggunakan default
opsi di bidang formulir apa pun:
$formBuilder->add('user', null, array('default' => $this->getUser()));
$formBuilder->add('foo', null, array('default' => 'bar'));
Jangan gunakan:
'data' => 'Default value'
Baca di sini: https://symfony.com/doc/current/reference/forms/types/form.html#data
"Opsi data selalu mengesampingkan nilai yang diambil dari data domain (objek) saat rendering. Ini berarti nilai objek juga ditimpa ketika formulir mengedit objek yang sudah ada, menyebabkannya kehilangan nilai tetapnya ketika formulir dikirimkan."
Gunakan yang berikut ini:
Katakanlah, untuk contoh ini, Anda memiliki Entity Foo, dan ada bidang "aktif" (dalam contoh ini adalah CheckBoxType, tetapi prosesnya sama untuk setiap jenis lainnya), yang ingin Anda periksa secara default
Di kelas FooFormType Anda, tambahkan:
...
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()
alih-alih membaca bidang mungkin membuatnya lebih baik.
Jadi saya mengerti masalahnya.
Anda ingin menyesuaikan cara formulir dibuat berdasarkan data di entitas Anda. Jika entitas sedang dibuat maka gunakan beberapa nilai default. Jika entitas yang ada gunakan nilai database.
Secara pribadi, saya pikir solusi @ MolecularMans adalah cara untuk pergi. Saya benar-benar akan menetapkan nilai default di konstruktor atau dalam pernyataan properti. Tetapi Anda sepertinya tidak menyukai pendekatan itu.
Sebaliknya, Anda dapat mengikuti ini: http://symfony.com/doc/current/cookbook/form/dynamic_form_modification.html
Anda menggantung pendengar pada jenis formulir Anda dan kemudian Anda dapat memeriksa entitas Anda dan menyesuaikan pembangun-> menambahkan pernyataan sesuai berdasarkan memiliki entitas baru atau yang sudah ada. Anda masih perlu menentukan nilai-nilai default Anda di suatu tempat meskipun Anda bisa kode mereka di pendengar Anda. Atau meneruskannya ke dalam bentuk formulir.
Sepertinya banyak pekerjaan. Lebih baik hanya meneruskan entitas ke formulir dengan nilai-nilai defaultnya sudah ditetapkan.
Seringkali, untuk nilai standar init saya menggunakan fixture. Tentu cara ini tidak mudah, tetapi sangat nyaman.
Contoh:
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();
}
}
Namun, bidang tipe symfony memiliki data opsi .
Contoh
$builder->add('token', 'hidden', array(
'data' => 'abcdef',
));
Ada cara yang sangat sederhana, Anda dapat mengatur default seperti di sini:
$defaults = array('sortby' => $sortby,'category' => $category,'page' => 1);
$form = $this->formfactory->createBuilder('form', $defaults)
->add('sortby','choice')
->add('category','choice')
->add('page','hidden')
->getForm();
Jika Anda menetapkan 'data' dalam formulir kreasi Anda, nilai ini tidak akan diubah saat mengedit entitas Anda.
Solusi saya adalah:
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',
));
}
Sampai jumpa.
'data' => $data['myfield'] ?? 'Default value',
Nilai default ditetapkan dengan mengkonfigurasi entitas yang sesuai. Sebelum mengikat entitas ke bentuk, setel bidang warnanya ke "# 0000FF":
// controller action
$project = new Project();
$project->setColor('#0000FF');
$form = $this->createForm(new ProjectType(), $project);
Jika bidang itu terikat pada suatu entitas (adalah properti dari entitas itu), Anda dapat menetapkan nilai default untuknya.
Sebuah contoh:
public function getMyField() {
if (is_null($this->MyField)) {
$this->setMyField('my default value');
}
return $this->MyField;
}
Saya biasanya hanya menetapkan nilai default untuk bidang tertentu di entitas saya:
/**
* @var int
* @ORM\Column(type="integer", nullable=true)
*/
protected $development_time = 0;
Ini akan berfungsi untuk catatan baru atau jika hanya memperbarui yang sudah ada.
'empty_data'
sebuah panggilan balik digunakan untuk memungkinkan param konstruktor pada entitas.
Seperti yang Brian tanyakan:
empty_data tampaknya hanya mengatur bidang ke 1 saat itu dikirimkan tanpa nilai. Bagaimana dengan ketika Anda ingin form secara default menampilkan 1 pada input ketika tidak ada nilai?
Anda dapat mengatur nilai default dengan empty_value
$builder->add('myField', 'number', ['empty_value' => 'Default value'])