Now, we will proceed to create our Web API Controller.
An “Add New Item” dialog box will open. Select ASP.NET from the left panel, then select “API Controller Class” from templates panel and put the name as EmployeeController.cs. Press OK.
Let’s understand this code. At the top we have defined an interface “FetchEmployeeDataState” which has two properties –
- empList of type “EmployeeData” class to hold the employee data.
- loading of type “boolean” to indicate if the data is being loaded onto the page.
After this, we have defined a component class “FetchEmployee” which inherits the abstract class React.Component. Inside the constructor of this class, we are calling the base class constructor using Super() and then initializing the fields of the interface to their default values.
We are also calling our web API method using fetch and set the empList value and also set the loading to false. The fetch method is invoked inside the constructor so that the employee data will be displayed as the page loads.
At the end of constructor, we are binding
handleDelete and
handleEdit method. This binding is necessary to make “this” work in the callback.
Then we have our “render()” method which will render our HTML elements onto the DOM. We will check if the data has finished loading or not and then call renderEmployeeTable method which will return an HTML table to display all the employee data on the web page. Every row of the table also had two action method – Edit and Delete for editing and deleting the employee record.
Next, we have handleDelete method which accepts employeeID as a parameter. This will prompt the user with a confirmation box and if the user selects yes then it will delete the employee with this employeeID.
The handleEdit method will invoke an edit request on the employee record by passing the employee id in the URL parameter and redirects to AddEmployee component.
At the end, we have defined an EmployeeData class having the same properties as of our
TblEmployee Model class to hold the employee data.
AddEmployee Component
Open AddEmployee.tsx file and put the following code into it:
- import * as React from 'react';
- import { RouteComponentProps } from 'react-router';
- import { Link, NavLink } from 'react-router-dom';
- import { EmployeeData } from './FetchEmployee';
-
- interface AddEmployeeDataState {
- title: string;
- loading: boolean;
- cityList: Array<any>;
- empData: EmployeeData;
- }
-
- export class AddEmployee extends React.Component<RouteComponentProps<{}>, AddEmployeeDataState> {
- constructor(props) {
- super(props);
-
- this.state = { title: "", loading: true, cityList: [], empData: new EmployeeData };
-
- fetch('api/Employee/GetCityList')
- .then(response => response.json() as Promise<Array<any>>)
- .then(data => {
- this.setState({ cityList: data });
- });
-
- var empid = this.props.match.params["empid"];
-
-
- if (empid > 0) {
- fetch('api/Employee/Details/' + empid)
- .then(response => response.json() as Promise<EmployeeData>)
- .then(data => {
- this.setState({ title: "Edit", loading: false, empData: data });
- });
- }
-
-
- else {
- this.state = { title: "Create", loading: false, cityList: [], empData: new EmployeeData };
- }
-
-
- this.handleSave = this.handleSave.bind(this);
- this.handleCancel = this.handleCancel.bind(this);
- }
-
- public render() {
- let contents = this.state.loading
- ? <p><em>Loading...</em></p>
- : this.renderCreateForm(this.state.cityList);
-
- return <div>
- <h1>{this.state.title}</h1>
- <h3>Employee</h3>
- <hr />
- {contents}
- </div>;
- }
-
-
- private handleSave(event) {
- event.preventDefault();
- const data = new FormData(event.target);
-
-
- if (this.state.empData.employeeId) {
- fetch('api/Employee/Edit', {
- method: 'PUT',
- body: data,
-
- }).then((response) => response.json())
- .then((responseJson) => {
- this.props.history.push("/fetchemployee");
- })
- }
-
-
- else {
- fetch('api/Employee/Create', {
- method: 'POST',
- body: data,
-
- }).then((response) => response.json())
- .then((responseJson) => {
- this.props.history.push("/fetchemployee");
- })
- }
- }
-
-
- private handleCancel(e) {
- e.preventDefault();
- this.props.history.push("/fetchemployee");
- }
-
-
- private renderCreateForm(cityList: Array<any>) {
- return (
- <form onSubmit={this.handleSave} >
- <div className="form-group row" >
- <input type="hidden" name="employeeId" value={this.state.empData.employeeId} />
- </div>
- < div className="form-group row" >
- <label className=" control-label col-md-12" htmlFor="Name">Name</label>
- <div className="col-md-4">
- <input className="form-control" type="text" name="name" defaultValue={this.state.empData.name} required />
- </div>
- </div >
- <div className="form-group row">
- <label className="control-label col-md-12" htmlFor="Gender">Gender</label>
- <div className="col-md-4">
- <select className="form-control" data-val="true" name="gender" defaultValue={this.state.empData.gender} required>
- <option value="">-- Select Gender --</option>
- <option value="Male">Male</option>
- <option value="Female">Female</option>
- </select>
- </div>
- </div >
- <div className="form-group row">
- <label className="control-label col-md-12" htmlFor="Department" >Department</label>
- <div className="col-md-4">
- <input className="form-control" type="text" name="Department" defaultValue={this.state.empData.department} required />
- </div>
- </div>
- <div className="form-group row">
- <label className="control-label col-md-12" htmlFor="City">City</label>
- <div className="col-md-4">
- <select className="form-control" data-val="true" name="City" defaultValue={this.state.empData.city} required>
- <option value="">-- Select City --</option>
- {cityList.map(city =>
- <option key={city.cityId} value={city.cityName}>{city.cityName}</option>
- )}
- </select>
- </div>
- </div >
- <div className="form-group">
- <button type="submit" className="btn btn-default">Save</button>
- <button className="btn" onClick={this.handleCancel}>Cancel</button>
- </div >
- </form >
- )
- }
- }
This component will be used for both adding and editing the employee data. Since we will use EmployeeData class to hold the data, we have imported it from FetchEmployee component.
The interface AddEmployeeDataState has four properties.
- title – to show “Create” or “Edit” on the top of the page
- loading – to check if the page has finished loading data
- cityList – to hold the list of cities from tblCities table
- empData – to hold the employee data to bind it to the HTML form
Inside the constructor of component class “AddEmployee” we are initializing the fields of the interface to their default value and then setting the value of
CityList property by fetching the data from
tblCities table. We will use this to bind a dropdown in our HTML form. Since we are fetching the city list inside our constructor, the dropdown list will be populated as the page loads.
This component will handle both Add and Edit request. So how will the system differentiate between both requests? The answer is routing. We need to define two different route parameters, one for Add employee record and another to edit employee record. We will be defining these in routes.tsx file shortly.
If an edit request is made then the employee id will be passed in the parameter. Inside the constructor, we will read the value of URL parameter empid. If the value of empid is greater than zero then this is an edit request and we will set the value of title to “Edit”, fill the data in empData property and set loading to false.
If the empid value is not set then it is an add request and we will set the value of title to “Create” and set loading to false.
The handleSave method will handle the save event on the form. Based on whether the URL has empid parameter or not we will send a request for PUT or POST and upon success, redirect the user back to FectchEmployee component.
The
renderCreateForm method will return an HTML form to be displayed on the webpage. We have set the default value in all the fields of the Form. If an Add request is made then all the fields will empty. If an edit request is made then it will fill the data of the corresponding employee in the fields. We bind the select element using
cityList property that we have populated in our constructor.
At this point in time, you might get an error “Parameter 'props' implicitly has an 'any' type” in AddEmployee.tsx file.
If you encounter this issue, then add the following line inside tsconfig.json file.
"noImplicitAny": false
Defining route and navigation menu for our Application
Open
ClientApp/routes.tsx file and put the following code in to it.
- import * as React from 'react';
- import { Route } from 'react-router-dom';
- import { Layout } from './components/Layout';
- import { Home } from './components/Home';
- import { FetchEmployee } from './components/FetchEmployee';
- import { AddEmployee } from './components/AddEmployee';
-
- export const routes = <Layout>
- <Route exact path='/' component={Home} />
- <Route path='/fetchemployee' component={FetchEmployee} />
- <Route path='/addemployee' component={AddEmployee} />
- <Route path='/employee/edit/:empid' component={AddEmployee} />
- </Layout>;
In this file, we have defined the routes for our application as below.
- / - if base URL is hit then it will redirect to Home component
- /fetchemployee – It will redirect to FetchEmployee component
- /addemployee – it will redirect to AddEmployee component to add a new employee record
- /employee/edit/:empid – we are passing the employee id in the parameter. it will redirect to AddEmployee component to edit the exisiting employee data
The last thing remaining is to define navigation menu for our application. Open ClientApp/components/NavMenu.tsx file and put the following code to it.
- import * as React from 'react';
- import { Link, NavLink } from 'react-router-dom';
-
- export class NavMenu extends React.Component<{}, {}> {
- public render() {
- return <div className='main-nav'>
- <div className='navbar navbar-inverse'>
- <div className='navbar-header'>
- <button type='button' className='navbar-toggle' data-toggle='collapse' data-target='.navbar-collapse'>
- <span className='sr-only'>Toggle navigation</span>
- <span className='icon-bar'></span>
- <span className='icon-bar'></span>
- <span className='icon-bar'></span>
- </button>
- <Link className='navbar-brand' to={'/'}>ReactCrudDemo</Link>
- </div>
- <div className='clearfix'></div>
- <div className='navbar-collapse collapse'>
- <ul className='nav navbar-nav'>
- <li>
- <NavLink to={'/'} exact activeClassName='active'>
- <span className='glyphicon glyphicon-home'></span> Home
- </NavLink>
- </li>
- <li>
- <NavLink to={'/fetchemployee'} activeClassName='active'>
- <span className='glyphicon glyphicon-th-list'></span> Fetch employee
- </NavLink>
- </li>
- </ul>
- </div>
- </div>
- </div>;
- }
- }
And that’s it. We have created our ASP.NET Core application using React.js and Entity Framework core database first approach.
Execution Demo
Press F5 to launch the application.
A web page will open as shown in the image below. Notice the navigation menu on the left showing navigation link for Home and Fetch Employee pages.
Click on Fetch Employee in the navigation menu. It will redirect to FetchEmployee component and displays all the employee data on the page. Notice the URL has “/fetchemployee” appended to it as we have defined in our routes.tsx file.
Since we have not added any data, hence it is empty.
Click on
CreateNew to navigate to
/addemployee page. Add a new Employee record as shown in the image below. You can observe that the
City field is a dropdown list, containing all the city names that we have inserted into tblCities table.
After inserting the data in all the fields, click on "Save" button. The new employee record will be created and you will be redirected to the /fetchemployee page, displaying records of all the employees. Here, we can also see action methods Edit and Delete.
If we want to edit an existing employee record, then click Edit action link. It will open Edit page as shown below where we can change the employee data. Notice that we have passed employee id in the URL parameter.
Here, we have changed the City of employee Neha from Bengaluru to Mumbai. Click on "Save" to return to the fetch-employee page to see the updated changes as highlighted in the image below.
Now, we will perform Delete operation on an employee named Rajesh having Employee ID 2. Click on Delete action link. It will open a JavaScript confirmation box asking for a confirmation to delete.
Once we click on "OK" the employee with name Rajesh will be removed from our record and you can see the updated list of the employee as shown below.
Conclusion
We have successfully created an ASP.NET Core application using React.js and Entity Framework core database first approach with the help of Visual Studio 2017 and SQL Server 2014. We have used HTML forms to get data from the user and bind the dropdown list to the database table using Entity framework.
You can fork this application on
GitHub and let me know your valuable feedback in the comments section below.