Symfony2 嵌入式表单删除按钮功能
Symfony2 Embedded forms delete button functionality
我在 Symfony2 中创建了一个嵌入式表单,其中有多个 "Employees" 合而为一 "Department"。现在,添加许多具有 "Firstname" 和 "Lastname" 的员工在 "Department" 表单上工作正常(我为此使用了 jQuery)。我想要表单上的 "Delete" 按钮功能,我无法弄清楚。谁能帮我弄一下删除按钮功能?
DepartmentType.php
<?php
namespace InstituteEvents\FormBundle\Form;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
class DepartmentType extends AbstractType
{
/**
* @param FormBuilderInterface $builder
* @param array $options
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('name')
->add('employees','collection', array(
'type' => new EmployeeType(),
'prototype' => true,
'allow_add' => true,
'by_reference' =>false
))
;
}
/**
* @param OptionsResolverInterface $resolver
*/
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'InstituteEvents\FormBundle\Entity\Department'
));
}
/**
* @return string
*/
public function getName()
{
return 'department';
}
}
EmployeeType.php
<?php
namespace InstituteEvents\FormBundle\Form;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
class EmployeeType extends AbstractType
{
/**
* @param FormBuilderInterface $builder
* @param array $options
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('firstname')
->add('lastname')
;
}
/**
* @param OptionsResolverInterface $resolver
*/
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'InstituteEvents\FormBundle\Entity\Employee'
));
}
/**
* @return string
*/
public function getName()
{
return 'employee';
}
}
index.html.twig - 此文件包含 jQuery 中的 "add employees" 按钮功能。这里我想要 "delete employees" 按钮 + 功能。我不知道 javascript 或 jQuery 正确,所以我需要帮助来添加 "delete employees" 按钮及其代码。
<script src="http://code.jquery.com/jquery-1.9.1.min.js"></script>
<script>
$(function() {
var index = 0;
var prototype = $('ul.form-employees').data('prototype');
$('#form-employee-btn').on('click', function() {
var newForm = prototype.replace(/__name__/g, index++);
var newLi = $('<li></li>');
newLi.append(newForm);
$(this).before(newLi);
});
});
</script>
<form method = "post">
{{ form_label(form.name, 'Department Name') }}
{{ form_widget(form.name) }}
<ul class="form-employees" data-prototype = "{{ form_widget(form.employees.vars.prototype)|e }}">
<input id="form-employee-btn" type="button" value="Add Employees"/>
</ul>
{{ form_widget(form._token) }}
<input type="submit" value="Submit"/>
</form>
按照说明找到in the docs:
在您的 DepartmentType
表单 class 中,将 EmployeeType
集合的 allow_delete
属性设置为 true
:
$builder
->add('name')
->add('employees','collection', array(
'type' => new EmployeeType(),
'prototype' => true,
'allow_add' => true,
'allow_delete' => true,//add this
'by_reference' =>false
)
);
接下来,添加删除按钮(通过 EmployeeType
表单中的构建器 (->add('delete', 'button')
),或手动添加(在模板中使用 JS)。然后将事件侦听器附加到表单. 假设您已经像这样添加了删除按钮:
//EmployeeType:
$builder->add('delete', 'button', ['attr' => ['class' => 'delete-employee']]);
如果您在视图中使用 JS 添加按钮,那么这段代码应该可以解决问题:
$('#department-form-selector').children('employee-form-selector').each(function(i)
{
$(this).append('<button name="delete' + i + '" class="delete-employee">Delete</button>');
});
添加(或即将添加)按钮后,使用 jQ 附加一个侦听器。按钮在这个阶段不需要在 DOM 中,因为我们使用的是事件委托,而不是直接绑定:
$('#department-form-selector').on('click', '.delete-employee', function()
{
$(this).closest('form').delete();//remove element
//optionally submit department form via AJAX call to persist the delete
return false;//stop event
});
现在,要处理表单(假设实体设置正确):
//in the controller that handles the form:
if ($form->isValid())
{
//1 => we need to query for the data in the DB, so we know what to delete
$current = $service->getCurrentDepartmentWithEmployees();
//get the current employees, that need to be updated
$oldEmployees = new ArrayCollection();
foreach ($current->getEmployees() as $employee)
$oldEmployees->add($employee);
//2 => get the form data
$department = $form->getData();
//3 => check if one or more eployees were deleted
foreach ($oldEmployees as $employee)
{
if (!$department->getEmployees()->contains($employee))
{//employee was removed, update entity/entities
$current->getEmployees()->removeElement($employee);
//depending on the relations you've specified:
$employee->setDepartment(null);
$em->persist($employee);
$em->persist($current);
}
}
$em->flush();
}
请注意,此代码未经测试。最坏情况删除的基本流程(双向,一对多关系倒过来,但是没有设置ondelete级联限制)
使用此代码作为参考,您应该能够解决这个问题
我在 Symfony2 中创建了一个嵌入式表单,其中有多个 "Employees" 合而为一 "Department"。现在,添加许多具有 "Firstname" 和 "Lastname" 的员工在 "Department" 表单上工作正常(我为此使用了 jQuery)。我想要表单上的 "Delete" 按钮功能,我无法弄清楚。谁能帮我弄一下删除按钮功能?
DepartmentType.php
<?php
namespace InstituteEvents\FormBundle\Form;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
class DepartmentType extends AbstractType
{
/**
* @param FormBuilderInterface $builder
* @param array $options
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('name')
->add('employees','collection', array(
'type' => new EmployeeType(),
'prototype' => true,
'allow_add' => true,
'by_reference' =>false
))
;
}
/**
* @param OptionsResolverInterface $resolver
*/
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'InstituteEvents\FormBundle\Entity\Department'
));
}
/**
* @return string
*/
public function getName()
{
return 'department';
}
}
EmployeeType.php
<?php
namespace InstituteEvents\FormBundle\Form;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
class EmployeeType extends AbstractType
{
/**
* @param FormBuilderInterface $builder
* @param array $options
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('firstname')
->add('lastname')
;
}
/**
* @param OptionsResolverInterface $resolver
*/
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'InstituteEvents\FormBundle\Entity\Employee'
));
}
/**
* @return string
*/
public function getName()
{
return 'employee';
}
}
index.html.twig - 此文件包含 jQuery 中的 "add employees" 按钮功能。这里我想要 "delete employees" 按钮 + 功能。我不知道 javascript 或 jQuery 正确,所以我需要帮助来添加 "delete employees" 按钮及其代码。
<script src="http://code.jquery.com/jquery-1.9.1.min.js"></script>
<script>
$(function() {
var index = 0;
var prototype = $('ul.form-employees').data('prototype');
$('#form-employee-btn').on('click', function() {
var newForm = prototype.replace(/__name__/g, index++);
var newLi = $('<li></li>');
newLi.append(newForm);
$(this).before(newLi);
});
});
</script>
<form method = "post">
{{ form_label(form.name, 'Department Name') }}
{{ form_widget(form.name) }}
<ul class="form-employees" data-prototype = "{{ form_widget(form.employees.vars.prototype)|e }}">
<input id="form-employee-btn" type="button" value="Add Employees"/>
</ul>
{{ form_widget(form._token) }}
<input type="submit" value="Submit"/>
</form>
按照说明找到in the docs:
在您的 DepartmentType
表单 class 中,将 EmployeeType
集合的 allow_delete
属性设置为 true
:
$builder
->add('name')
->add('employees','collection', array(
'type' => new EmployeeType(),
'prototype' => true,
'allow_add' => true,
'allow_delete' => true,//add this
'by_reference' =>false
)
);
接下来,添加删除按钮(通过 EmployeeType
表单中的构建器 (->add('delete', 'button')
),或手动添加(在模板中使用 JS)。然后将事件侦听器附加到表单. 假设您已经像这样添加了删除按钮:
//EmployeeType:
$builder->add('delete', 'button', ['attr' => ['class' => 'delete-employee']]);
如果您在视图中使用 JS 添加按钮,那么这段代码应该可以解决问题:
$('#department-form-selector').children('employee-form-selector').each(function(i)
{
$(this).append('<button name="delete' + i + '" class="delete-employee">Delete</button>');
});
添加(或即将添加)按钮后,使用 jQ 附加一个侦听器。按钮在这个阶段不需要在 DOM 中,因为我们使用的是事件委托,而不是直接绑定:
$('#department-form-selector').on('click', '.delete-employee', function()
{
$(this).closest('form').delete();//remove element
//optionally submit department form via AJAX call to persist the delete
return false;//stop event
});
现在,要处理表单(假设实体设置正确):
//in the controller that handles the form:
if ($form->isValid())
{
//1 => we need to query for the data in the DB, so we know what to delete
$current = $service->getCurrentDepartmentWithEmployees();
//get the current employees, that need to be updated
$oldEmployees = new ArrayCollection();
foreach ($current->getEmployees() as $employee)
$oldEmployees->add($employee);
//2 => get the form data
$department = $form->getData();
//3 => check if one or more eployees were deleted
foreach ($oldEmployees as $employee)
{
if (!$department->getEmployees()->contains($employee))
{//employee was removed, update entity/entities
$current->getEmployees()->removeElement($employee);
//depending on the relations you've specified:
$employee->setDepartment(null);
$em->persist($employee);
$em->persist($current);
}
}
$em->flush();
}
请注意,此代码未经测试。最坏情况删除的基本流程(双向,一对多关系倒过来,但是没有设置ondelete级联限制)
使用此代码作为参考,您应该能够解决这个问题