Symfony 4中的动态表单内容更改

时间:2018-09-03 19:12:44

标签: php symfony symfony4

我要在表单中使用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提交表单。如果数据库中存在带有相应“用户”和“地址”的标签,则将来自数据库的文本预加载到文本字段中,以便用户可以看到该标签已经存在并且可以对其进行编辑。否则,只需显示一个空白框,然后按保存即可创建一个新标签。

1 个答案:

答案 0 :(得分:1)

首先,您需要将表单绑定到标签类。因此,在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();
});

您的“检查标签”路线的控制器应如下所示:

/**
 * @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]);
}

最后,准备就绪后,您可以正确提交表单。当您只需要检查标签是否存在并获取其文本时,就无需进行验证等。

注意:

  • 上面的代码假设您使用主义来处理数据库连接。否则,请正确修改代码。
  • 您应该使用FOSJsRoutingBundle在javascript中生成路由,而不是像我的示例那样对它们进行硬编码。这就是我的路由配置中使用的选项Exposure = true。
  • 您将不得不再次检查标记是否存在于您处理表单提交的控制器中,否则,当尝试保留已存在的标记时,将出现重复插入的错误。
  • 当然,您必须对我的代码进行一些更改,特别是如果您不使用jQuery。