Symfony表单组件能否与React.js一起使用?

3

我正在使用Symfony表单组件,我的项目中有很多表单。

要完全学习表单组件需要走很长的路程,但现在我喜欢它。我也喜欢自动验证等功能。

所以,现在我想在我的项目中学习并使用React.js。

但是看起来,我不能像以前那样使用验证和表单构建器来进行项目?我这样说对吗?

Original Answer翻译成"最初的回答"

3个回答

6
虽然在API上下文中,您不会使用表单组件来实际呈现HTML格式的表单($form->createView()方法),但您仍然可以从它所提供的所有魔力中受益:验证、表单事件等等。无论是否使用API,我个人认为您应该始终在控制器 mutations 中使用表单类型。
例如,在使用FOSRestBundle时,考虑以下简单的控制器操作:
/**
 * @Rest\Put("posts/edit/{id}", name="posts.edit", requirements={"id"="\d+"})
 *
 * @param Post $post
 * @param Request $request
 *
 * @return Post
 *
 * @throws BadRequestException
 *
 */
public function edit(Post $post, Request $request): Post
{
    $form = $this->createForm(PostType::class, $user);
    $form->handleRequest($request);
    $form->submit($request->request->all());
    if ($form->isValid()) {
        $em = $this->getDoctrine()->getManager();
        $em->persist($post);
        $em->flush();

        return $post;
    }

    // Any error handling of your taste.
    // You could consider expliciting form errors.
    throw new BadRequestException();
}

请注意,必须创建Post实体和PostType表单。在此上下文中,关于它们没有什么特别的内容,因此我不会详细说明。
另请注意,我们不检查表单是否已提交。在您的情况下,将表单呈现为HTML是React的工作,因此此操作不会用于获取任何数据,它专门是一个PUT路由。这意味着,任何到达此路由的请求都必须是包含正确数据的PUT请求,并由您手动在React中构建的HTML表单提交给我们的PostType来处理。
此外,稍微超出问题的范围,FOSRestBundle订阅您的操作返回的内容,并自动将其序列化为配置格式(在您的情况下,可能是JSON)。这意味着我们的操作示例可以返回两种可能的响应:
  • 一个状态代码为200的Response,其中包含我们序列化的Post。(您还可以考虑返回204并返回空值。)
  • 一个状态代码为400的Response,其中包含我们想要的任何内容(比如表单错误)。
请允许我引导您前往FOSRestBundle文档

好的,这听起来更好。我不想放弃整个FormType-Thing。 但我猜它总是会像这样 - 我可以从控制器获取我的错误消息,然后必须手动在React中路由这些消息。 对于具有表单继承和集合类型的大型复杂表单,这将需要很多工作。我不喜欢那样:D - Slowwie
2
你可以查看LiformBundleliform-react来满足你的需求。这可能是你正在寻找的缺失环节。 - Scolopendre

1

您可以毫无问题地使用由formBuilder创建的表单。

您必须使用axios获取您的表单并创建一个新组件,如下所示:

const url = 'localhost/post/new';
const ref = useRef(null);

const [form, setForm] = useState('');    
const fetchData = () => {
        axios.get(url))
            .then(function (response){
                setForm(response.data);
            })
            .catch(function (error){
                //something
            })
        ;
    }

const MyComponent = () => {
        useEffect(() => {
            const element = ref.current.firstChild;
            if (ref.current.firstChild === null)
                return;

            element.addEventListener('submit', () => {handleSave(event)});
            return () => {
                element.removeEventListener('submit', () => {handleSave(event)});
            };
        }, []);

        return (
            <div ref={ref} dangerouslySetInnerHTML={{ __html: form }} />
        );
    };

const handleSave = (event) => {
        event.preventDefault();
        let formData = new FormData(event.target)
        let action = event.target.action;
        let files = event.target.querySelectorAll('[type="file"]');
        if (files)
            files.forEach((file) => {
                formData.set(file.name, file.files[0])
            });
        axios.post(action, formData)
            .then(function (response) {
                Swal.fire({
                    icon: 'success',
                    title: response.data.message,
                    showConfirmButton: false,
                    timer: 1500
                })
            //Do something else
            })
            .catch(function (error) {
                error.response.status === 422 ?
                    setForm(error.response.data)
                    :
                    console.log(error);
            });
    }

return (<MyComponent/>);

现在,您可以使用HTML组件获取表单并使用React组件呈现它。

如果出现验证错误,则会收到422状态,并且您可以使用setForm()替换表单。

在您的Symfony控制器中,您必须设置类似于以下内容:

#[Route('/post/{state}/{id}', name: 'post', defaults: ['state' => null, 'id' => null])]
public function post(
    ?string $state,
    ?int $id,
    Request $request,
    EntityManagerInterface $em
): JsonResponse|Response
{
    if ($state == 'new') {
        $post = new Post();
        $form = $this->createFormBuilder()
            ->add('title', TextType::class)
            ->add('content', TextareaType::class);

        $form = $form->getForm();
        $form->handleRequest($request);
        if ($form->isSubmitted() and $form->isValid()) {
            $em->persist($post);
            $em->flush();

            return $this->json(['message' => 'post added!'], 200);
        }

        return $this->renderForm('{{ form(form) }}', [
            'form' => $form
        ]);
    }
}

我已将此函数仅用于表单,但您可以将其用于所有请求。

0

可能不是因为您的表单是用于服务器使用的:验证/显示错误/数据规范化/净化等。

通常,您使用React来显示HTML并使用API将其连接到服务器。


1
是的,我知道 - 但是要使用ajax发送表单 - 我认为React与表单组件配合得更好。 - Slowwie

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接