Month: September 2022

React Js Development

CRUD Operation through React and Symfony

Hello Folks!In this blog we are discussing about React JS and Symfony. Here we need to understand what is react JS? how actually it works with Symfony? How can we use them together to perform crud operation. What is React JS ? React is a JavaScript library developed by Facebook. It’s aim is to allow developers to easily create fast user interfaces for websites and applications alike. The main concept of React. js is virtual DOM. It is also used among other things, and was used to build Instagram.com too. Why we use React JS ? One of the main benefits of using React JS is its potential to reuse components. It saves time for developers as they don’t have to write various codes for the same features. Furthermore, if any changes are made in any particular part, it will not affect other parts of the application. React is an excellent tool with which to create interactive applications for mobile, web, and other platforms. React’s popularity and usage are increasing day by day for good reason. As a developer, coding in React makes you better at JavaScript, a language that holds nearly 90% of the web development share today. How to build a CRUD operation through React and Symfony is given below: src/Controller/ProjectController.php <?php namespace App\Controller; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\Routing\Annotation\Route; use Symfony\Component\HttpFoundation\Request; use App\Entity\Project; /** * @Route(“/api”, name=”api_”) */ class ProjectController extends AbstractController { /** * @Route(“/project”, name=”project_index”) */ public function index(): Response { $products = $this->getDoctrine()->getRepository(Project::class)->findAll(); $data = []; foreach ($products as $product){ $data[] = [ ‘id’ => $product->getId(), ‘name’ => $product->getName(), ’email’ => $product->getEmail(), ‘number’ => $product->getNumber(), ‘address’ => $product->getAddress(), ]; } return $this->json($data); } /** * @Route(“/project/create”, name=”project_new”) */ public function new(Request $request): Response { $em = $this->getDoctrine()->getManager(); $project = new Project(); $project->setName($request->request->get(‘name’)); $project->setEmail($request->request->get(’email’)); $project->setNumber($request->request->get(‘number’)); $project->setAddress($request->request->get(‘address’)); $em->persist($project); $em->flush(); return $this->json(‘Created new project successfully.’); } /** * @Route(“/project/{id}”, name=”project_show”) */ public function show(int $id): Response { $project = $this->getDoctrine()->getRepository(Project::class)->find($id); if(!$project){ return $this->json(‘No project found for this ID.’); } $data = [ ‘id’ => $project->getId(), ‘name’ => $project->getName(), ’email’ => $project->getEmail(), ‘number’ => $project->getNumber(), ‘address’ => $project->getAddress(), ]; return $this->json($data); } /** * @Route(“/project/edit/{id}”, name=”project_edit”) */ public function edit(Request $request, int $id): Response { $em = $this->getDoctrine()->getManager(); $project = $em->getRepository(Project::class)->find($id); if(!$project){ return $this->json(‘No project was for the ID.’); } $content = json_decode($request->getContent()); $project->setName($content->name); $project->setEmail($content->email); $project->setNumber($content->number); $project->setAddress($content->address); $em->flush(); $data = [ ‘id’ => $project->getId(), ‘name’ => $project->getName(), ’email’ => $project->getEmail(), ‘number’ => $project->getNumber(), ‘address’ => $project->getAddress(), ]; return $this->json($data); } /** * @Route(“/project/delete/{id}”, name=”project_delete”) */ public function delete(int $id): Response { $em = $this->getDoctrine()->getManager(); $project = $em->getRepository(Project::class)->find($id); if(!$project){ return $this->json(‘No Project was found by this ID.’); } $em->remove($project); $em->flush(); return $this->json(‘The project is successfully deleted.’); } } /src/Entity/Project.php <?php namespace App\Entity; use App\Repository\ProjectRepository; use Doctrine\ORM\Mapping as ORM; /** * @ORM\Entity(repositoryClass=ProjectRepository::class) */ class Project { /** * @ORM\Id * @ORM\GeneratedValue * @ORM\Column(type=”integer”) */ private $id; /** * @ORM\Column(type=”string”, length=255) */ private $name; /** * @ORM\Column(type=”string”, length=255) */ private $email; /** * @ORM\Column(type=”string”, length=15, nullable=true) */ private $number; /** * @ORM\Column(type=”string”, length=255) */ private $address; public function getId(): ?int { return $this->id; } public function getName(): ?string { return $this->name; } public function setName(?string $name): self { $this->name = $name; return $this; } public function getEmail(): ?string { return $this->email; } public function setEmail(string $email): self { $this->email = $email; return $this; } public function getNumber(): ?int { return $this->number; } public function setNumber(int $number): self { $this->number = $number; return $this; } public function getAddress(): ?string { return $this->address; } public function setAddress(string $address): self { $this->address = $address; return $this; } } /src/Controller/SpaController.php <?php namespace App\Controller; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\Routing\Annotation\Route; class SpaController extends AbstractController { /** * @Route(“/{reactRouting}”, name=”app_home”, requirements={“reactRouting”=”^(?!api).+”}, defaults={“reactRouting”: null}) */ public function index() { return $this->render(‘spa/index.html.twig’, [ ‘controller_name’ => ‘SpaController’, ]); } } /templates/base.html.twig <!DOCTYPE html> <html> <head> <meta charset=”UTF-8″> <title>{% block title %}Symfony React{% endblock %}</title> {% block stylesheets %} {{ encore_entry_link_tags(‘app’) }} {% endblock %} <link href=”” rel=”stylesheet” integrity=”sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC” crossorigin=”anonymous”> <script src=”https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/js/bootstrap.bundle.min.js” integrity=”sha384-MrcW6ZMFYlzcLA8Nl+NtUVF0sA7MsXsP1UyJoMp4YLEuNSfAP+JcXn/tWtIaxVXM” crossorigin=”anonymous”></script> </head> <body> {% block body %}{% endblock %} {% block javascripts %} {{ encore_entry_script_tags(‘app’) }} {% endblock %} </body> </html> /templates/spa/index.html.twig {% extends ‘base.html.twig’ %} {% block body %} <div id=”app”></div> {% endblock %} Now, We will Install Encore and React Dependencies through command as below :Firstly, we will install Symfony Webpack Encore Bundle by running the following commands.1) composer require symfony/webpack-encore-bundle2) yarn installSecondly, We will now install the dependencies by running the following commands.1) yarn add @babel/preset-react –dev2) yarn add react-router-dom3) yarn add –dev react react-dom prop-types axios4) yarn add @babel/plugin-proposal-class-properties @babel/plugin-transform-runtimeAnd Lastly, we will add sweetalert for getting the beautiful pop-ups for our actions. To install it, run the following command.npm install sweetalert2Now, it will generate webpack.config.js file. assets/Main.js import React from ‘react’; import ReactDOM from ‘react-dom’; import { BrowserRouter as Router, Routes, Route } from “react-router-dom”; import ProjectList from “./pages/ProjectList” import ProjectCreate from “./pages/ProjectCreate” import ProjectEdit from “./pages/ProjectEdit” import ProjectShow from “./pages/ProjectShow” function Main() { return ( <Router> <Routes> <Route exact path=”/” element={<ProjectList/>} /> <Route path=”/create” element={<ProjectCreate/>} /> <Route path=”/edit/:id” element={<ProjectEdit/>} /> <Route path=”/show/:id” element={<ProjectShow/>} /> </Routes> </Router> ); } export default Main; if (document.getElementById(‘app’)) { ReactDOM.render(<Main />, document.getElementById(‘app’)); } /assets/app.js /* * Welcome to your app’s main JavaScript file! * * We recommend including the built version of this JavaScript file * (and its CSS file) in your base layout (base.html.twig). */ // any CSS you import will output into a single css file (app.css in this case) import ‘./styles/app.css’; // start the Stimulus application import ‘./bootstrap’; require(‘./Main’); /assets/components/Layout.js import React from ‘react’; const Layout =({children}) =>{ return( <div className=”container”> {children} </div> ) } export default Layout; /assets/pages/ProjectCreate.js import React, {useState} from ‘react’; import { Link } from “react-router-dom”; import Layout from “../components/Layout” import Swal from ‘sweetalert2’ import axios from ‘axios’; function ProjectCreate() { const [name, setName] = useState(”); const [email, setEmail] = useState(”); const [number, setNumber] = useState(”); const [address, setAddress] = useState(”) const [isSaving, setIsSaving] = useState(false) const handleSave = () => { setIsSaving(true); let formData = new FormData() formData.append(“name”, name) formData.append(“email”, email) formData.append(“number”, number) formData.append(“address”, address) console.log(‘formdata’, formData); axios.post(‘/api/project/create’, formData) .then(function (response) { Swal.fire({ icon: ‘success’, title: ‘Project saved successfully!’, showConfirmButton: false, timer: 1500 }) setIsSaving(false); setName(”) setEmail(”) setNumber(”) setAddress(”) }) .catch(function (error) { Swal.fire({ icon: ‘error’, title: ‘An Error Occured!’, showConfirmButton: false, timer: 1500 }) setIsSaving(false) }); } return ( <Layout> <div className=”container”> <h2 className=”text-center mt-5 mb-3″>Create New Project</h2> <div className=”card”> <div className=”card-header”> <Link className=”btn btn-outline-info float-right” to=”/”>View All Projects </Link> </div> <div className=”card-body”> <form> <div className=”form-group”> <label htmlFor=”name”>Name</label> <input onChange={(event)=>{setName(event.target.value)}} value={name} type=”text” className=”form-control” id=”name” name=”name”/> </div> <div className=”form-group”> <label htmlFor=”email”>Email</label> <input onChange={(event)=>{setEmail(event.target.value)}} value={email} type=”text” className=”form-control” id=”email” name=”email”/> </div> <div className=”form-group”> <label htmlFor=”number”>Number</label> <input onChange={(event)=>{setNumber(event.target.value)}} value={number} type=”text” className=”form-control” id=”number” name=”number”/> </div> <div className=”form-group”> <label htmlFor=”address”>Address</label> <textarea value={address} onChange={(event)=>{setAddress(event.target.value)}} className=”form-control” id=”address” rows=”3″ name=”address”></textarea> </div> <button disabled={isSaving} onClick={handleSave} type=”button” className=”btn btn-outline-primary mt-3″> Save Project </button> </form> </div> </div> </div> </Layout> ); } export default ProjectCreate; /assets/pages/ProjectEdit.js import React, { useState, useEffect } from ‘react’; import { Link, useParams } from “react-router-dom”; import Layout from “../components/Layout” import Swal from ‘sweetalert2’ import axios from ‘axios’; function ProjectEdit() { const [id, setId] = useState(useParams().id) const [name, setName] = useState(”); const [email, setEmail] = useState(”); const [number, setNumber] = useState(”); const [address, setAddress] = useState(”) const [isSaving, setIsSaving] = useState(false) useEffect(() => { axios.get(`/api/project/${id}`) .then(function (response) { let project = response.data setName(project.name); setEmail(project.email); setNumber(project.number); setAddress(project.address); }) .catch(function (error) { Swal.fire({ icon: ‘error’, title: ‘An Error Occured!’, showConfirmButton: false, timer: 1500 }) }) }, []) const handleSave = () => { setIsSaving(true); axios.patch(`/api/project/edit/${id}`, { name: name, email: email, number: number, address: address }) .then(function (response) { Swal.fire({ icon: ‘success’, title: ‘Project updated successfully!’, showConfirmButton: false, timer: 1500 }) setIsSaving(false); }) .catch(function (error) { Swal.fire({ icon: ‘error’, title: ‘An Error Occured!’, showConfirmButton: false, timer: 1500 }) setIsSaving(false) }); } return ( <Layout> <div className=”container”> <h2 className=”text-center mt-5 mb-3″>Edit Project</h2> <div className=”card”> <div className=”card-header”> <Link className=”btn btn-outline-info float-right” to=”/”>View All Projects </Link> </div> <div className=”card-body”> <form> <div className=”form-group”> <label htmlFor=”name”>Name</label> <input onChange={(event)=>{setName(event.target.value)}} value={name} type=”text” className=”form-control” id=”name” name=”name”/> </div> <div className=”form-group”> <label htmlFor=”email”>Email</label> <input onChange={(event)=>{setEmail(event.target.value)}} value={email} type=”text” className=”form-control” id=”email” name=”email”/> </div> <div className=”form-group”> <label htmlFor=”number”>Number</label> <input onChange={(event)=>{setNumber(event.target.value)}} value={number} type=”text” className=”form-control” id=”number” name=”number”/> </div> <div className=”form-group”> <label htmlFor=”address”>Address</label> <textarea value={address} onChange={(event)=>{setAddress(event.target.value)}} className=”form-control” id=”address” rows=”3″ name=”address”></textarea> </div> <button disabled={isSaving} onClick={handleSave} type=”button” className=”btn btn-outline-success mt-3″> Update Project </button> </form> </div> </div> </div> </Layout> ); } export default ProjectEdit; /assets/pages/ProjectList.js import React,{ useState, useEffect} from ‘react’; import { Link } from “react-router-dom”; import Layout from “../components/Layout” import Swal from ‘sweetalert2’ import axios from ‘axios’; function ProjectList() { const [projectList, setProjectList] = useState([]) useEffect(() => { fetchProjectList() }, []) const fetchProjectList = () => { axios.get(‘/api/project’) .then(function (response) { setProjectList(response.data); }) .catch(function (error) { console.log(error); }) } const handleDelete = (id) => { Swal.fire({ title: ‘Are you sure?’, text: “You won’t be able to revert this!”, icon: ‘warning’, showCancelButton: true, confirmButtonColor: ‘#d33’, cancelButtonColor: ‘#3085d6’, confirmButtonText: ‘Yes, delete it!’ }).then((result) => { if (result.isConfirmed) { axios.delete(`/api/project/delete/${id}`) .then(function (response) { Swal.fire({ icon: ‘success’, title: ‘Project deleted successfully!’, showConfirmButton: false, timer: 1500 }) fetchProjectList() }) .catch(function (error) { Swal.fire({ icon: ‘error’, title: ‘An Error Occured!’, showConfirmButton: false, timer: 1500 }) }); } }) } return ( <Layout> <div className=”container”> <h2 className=”text-center mt-5 mb-3″>Symfony/React Project</h2> <div className=”card”> <div className=”card-header”> <Link className=”btn btn-outline-primary” to=”/create”>Create New Project </Link> </div> <div className=”card-body”> <table className=”table table-bordered”> <thead> <tr> <th>No.</th> <th>Name</th> <th>Email</th> <th>Number</th> <th>Address</th> <th width=”240px”>Action</th> </tr> </thead> <tbody> {projectList.map((project, key)=>{ return ( <tr key={key}> <td>{project.id}</td> <td>{project.name}</td> <td>{project.email}</td> <td>{project.number}</td> <td>{project.address}</td> <td> <Link to={`/show/${project.id}`} className=”btn btn-outline-info mx-1″> Show </Link> <Link className=”btn btn-outline-success mx-1″ to={`/edit/${project.id}`}> Edit </Link> <button onClick={()=>handleDelete(project.id)} className=”btn btn-outline-danger mx-1″> Delete </button> </td> </tr> ) })} </tbody> </table> </div> </div> </div> </Layout> ); } export default ProjectList; /assets/pages/ProjectShow.js import React, {useState, useEffect} from ‘react’; import { Link, useParams } from “react-router-dom”; import Layout from “../components/Layout” import axios from ‘axios’; function ProjectShow() { const [id, setId] = useState(useParams().id) const [project, setProject] = useState({name:”, description:”}) useEffect(() => { axios.get(`/api/project/${id}`) .then(function (response) { setProject(response.data) }) .catch(function (error) { console.log(error); }) }, []) return ( <Layout> <div className=”container”> <h2 className=”text-center mt-5 mb-3″>Show Project</h2> <div className=”card”> <div className=”card-header”> <Link className=”btn btn-outline-info float-right” to=”/”> View All Projects </Link> </div> <div className=”card-body”> <b className=”text-muted”>Name:</b> <p>{project.name}</p> <b className=”text-muted”>Email:</b> <p>{project.email}</p> <b className=”text-muted”>Number:</b> <p>{project.number}</p> <b className=”text-muted”>Address:</b> <p>{project.address}</p> </div> </div> </div> </Layout> ); } export default ProjectShow; So, that’s the end of this quick CRUD operations in Symfony and React !If you get any error while performing the task, Let us know in the comment section below.
×