symfony 4 中的动态表单内容更改
Dynamic form content change in symfony 4
我有 3 个要在表单中使用的实体,用户、地址和标签。该标签通过其 ID 引用用户和地址:
mysql> describe user;
+-------+----------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------+----------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| name | longtext | NO | | NULL | |
+-------+----------+------+-----+---------+----------------+
2 rows in set (0.00 sec)
mysql> describe address;
+-------+----------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------+----------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| name | longtext | NO | | NULL | |
+-------+----------+------+-----+---------+----------------+
2 rows in set (0.00 sec)
mysql> describe tag;
+------------+----------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+------------+----------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| user_id | int(11) | YES | MUL | NULL | |
| address_id | int(11) | YES | MUL | NULL | |
| text | longtext | NO | | NULL | |
+------------+----------+------+-----+---------+----------------+
4 rows in set (0.00 sec)
我的表单生成器:
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('user',EntityType::class, [
'class' => User::class
])
->add('address', EntityType::class, [
'class' => Address::class
])
->add('text')
->add('save', SubmitType::class)
;
}
现在,我添加了一些 JS,以便在用户从下拉列表中更改所选用户或地址时提交表单。但是,如果所选用户和地址存在相应的标签,我想预先填充表单中的文本字段,以便用户可以对其进行编辑。有谁知道我如何在 symfony 中做到这一点?
Please check this image
更改时,用JS提交表单。如果数据库中存在具有相应用户和地址的标签,请在文本字段中预加载数据库中的文本,以便用户可以看到它已经存在并且可以进行编辑。否则只显示空框,按下保存时将创建一个新标签。
首先,您需要将表单绑定到标签 class。所以在 TagType.php 你将有:
public function configureOptions(OptionsResolver $resolver) {
$resolver->setDefaults([
'data_class' => Tag::class,
'csrf_token_id' => 'tag_form'
]);
}
有多种方法可以实现您想要的功能。例如,您可以在数据库中找到所有标签,列出它们,然后通过编辑按钮,编辑您想要的每个标签。然后你也将有一个创建按钮来创建新标签。
但是按照您选择的实现方式,您实际上不必在更改用户或地址时提交表单。您只需要创建一个 javascript 函数,如下所示:
function onChange(){
var userId = $('input#user_input').val();
var addressId = $('input#address_input').val();
$.post( "check-tag", { user: userId, address: addressId }).done(function( data ) {
if (data.tagText !== ""){
$( "input#text_input" ).val( data.tagText );
}
});
}
然后像这样绑定您的事件处理程序:
$('input#user_input, input#address_input').on('change', function() {
onChange();
});
'check-tag' 路线的控制器应如下所示:
/**
* @Route("/check-tag", name="check-tag", options={ "expose" = true })
*/
public function checkTag(Request $request, EntityManagerInterface $em) {
$userId = $request->request->get('user');
$addressId = $request->request->get('address');
$tagRepository = $em->getRepository(Tag::class);
$tag = $tagRepository->findBy(['user' => $userId, 'address' => $addressId]);
$tagText = $tag ? $tag->getText() : '';
return $this->json(['tagText' => $tagText]);
}
您终于可以在准备好时正确提交表单了。当您只需要检查标签是否存在并获取其文本时,无需验证等。
备注:
- 上面的代码假定您使用 doctrine 来处理您的数据库连接。如果没有,只需适当修改代码即可。
- 您应该使用 FOSJsRoutingBundle 在 javascript 中生成路由,而不是像我的示例那样对它们进行硬编码。这就是我的路由配置中使用选项 expose = true 的地方。
- 您将必须再次检查该标签是否存在于您处理表单提交的控制器中,否则在尝试保留已存在的标签时,您将收到重复插入的原则错误。
- 当然你必须稍微改变我的代码,特别是如果你不使用 jQuery。
我有 3 个要在表单中使用的实体,用户、地址和标签。该标签通过其 ID 引用用户和地址:
mysql> describe user;
+-------+----------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------+----------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| name | longtext | NO | | NULL | |
+-------+----------+------+-----+---------+----------------+
2 rows in set (0.00 sec)
mysql> describe address;
+-------+----------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------+----------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| name | longtext | NO | | NULL | |
+-------+----------+------+-----+---------+----------------+
2 rows in set (0.00 sec)
mysql> describe tag;
+------------+----------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+------------+----------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| user_id | int(11) | YES | MUL | NULL | |
| address_id | int(11) | YES | MUL | NULL | |
| text | longtext | NO | | NULL | |
+------------+----------+------+-----+---------+----------------+
4 rows in set (0.00 sec)
我的表单生成器:
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('user',EntityType::class, [
'class' => User::class
])
->add('address', EntityType::class, [
'class' => Address::class
])
->add('text')
->add('save', SubmitType::class)
;
}
现在,我添加了一些 JS,以便在用户从下拉列表中更改所选用户或地址时提交表单。但是,如果所选用户和地址存在相应的标签,我想预先填充表单中的文本字段,以便用户可以对其进行编辑。有谁知道我如何在 symfony 中做到这一点?
Please check this image
更改时,用JS提交表单。如果数据库中存在具有相应用户和地址的标签,请在文本字段中预加载数据库中的文本,以便用户可以看到它已经存在并且可以进行编辑。否则只显示空框,按下保存时将创建一个新标签。
首先,您需要将表单绑定到标签 class。所以在 TagType.php 你将有:
public function configureOptions(OptionsResolver $resolver) {
$resolver->setDefaults([
'data_class' => Tag::class,
'csrf_token_id' => 'tag_form'
]);
}
有多种方法可以实现您想要的功能。例如,您可以在数据库中找到所有标签,列出它们,然后通过编辑按钮,编辑您想要的每个标签。然后你也将有一个创建按钮来创建新标签。
但是按照您选择的实现方式,您实际上不必在更改用户或地址时提交表单。您只需要创建一个 javascript 函数,如下所示:
function onChange(){
var userId = $('input#user_input').val();
var addressId = $('input#address_input').val();
$.post( "check-tag", { user: userId, address: addressId }).done(function( data ) {
if (data.tagText !== ""){
$( "input#text_input" ).val( data.tagText );
}
});
}
然后像这样绑定您的事件处理程序:
$('input#user_input, input#address_input').on('change', function() {
onChange();
});
'check-tag' 路线的控制器应如下所示:
/**
* @Route("/check-tag", name="check-tag", options={ "expose" = true })
*/
public function checkTag(Request $request, EntityManagerInterface $em) {
$userId = $request->request->get('user');
$addressId = $request->request->get('address');
$tagRepository = $em->getRepository(Tag::class);
$tag = $tagRepository->findBy(['user' => $userId, 'address' => $addressId]);
$tagText = $tag ? $tag->getText() : '';
return $this->json(['tagText' => $tagText]);
}
您终于可以在准备好时正确提交表单了。当您只需要检查标签是否存在并获取其文本时,无需验证等。
备注:
- 上面的代码假定您使用 doctrine 来处理您的数据库连接。如果没有,只需适当修改代码即可。
- 您应该使用 FOSJsRoutingBundle 在 javascript 中生成路由,而不是像我的示例那样对它们进行硬编码。这就是我的路由配置中使用选项 expose = true 的地方。
- 您将必须再次检查该标签是否存在于您处理表单提交的控制器中,否则在尝试保留已存在的标签时,您将收到重复插入的原则错误。
- 当然你必须稍微改变我的代码,特别是如果你不使用 jQuery。