Editing entities without breaking the network tab (part 4/5)

Alex Marinov
Ignite UI
Published in
9 min readSep 25, 2019
Photo by Patrick Brinksma on Unsplash

This is the fourth step of our example for implementing batch editing with the Ignite UI for Angular Grid control and Web API. You may find the previous step, in which we have created the Angular application using the Ignite UI CLI, here.

Step 4: Update the Ignite UI CLI project in order to work with the Web API

In this section, we use:

  • Visual Studio Code

In order to explore the IgxGrid project and to identify what changes are required for our scenario, navigate to the root folder of the project, where the packages.json file is located. Right-click on the folder and select “Open with Code” from the menu. If you do not have Visual Studio Code installed on your machine — you may get it from here.

Now, when we have the whole file structure of the project opened in Code, expand src > app > grid-batch-editing.

Open the data.ts file. You see that it contains the dummy data the template is using. We do not need it, as we will feed the grid with our own data, so you may delete this file.

Now open the grid-batch-editing.component.ts file and from the imports at the top of the code remove:

We need to create an injectable service that will get the data from the back end and will also send the transactions we make to the server. We should also create a service interface that the service needs to get the data from the server.

You may read more about Angular Services and Dependency Injections here.

To create the interface, right-click the grid-batch-editing folder and select “New File”.

Name it city.ts. Paste the following code inside:

This is our interface that models our data source.

Now let us create the service that would use this interface. We may generate the service using the ng g command like this:

ng g service city

At this point, we must comply with the requests sending approach that we have made in step 2 of this tutorial. Below we demonstrate how our service would look like in case we have decided to use the “single request” to the server where our transactions would be processed.

If you have decided to use the second approach — where you process the transactions on the client-side and then send them to the server in separate requests, you should implement a different commitCities() method in this service. We will explain the differences below. Now let us begin with our example.

Paste the following code inside the newly created service:

Here, we set the endpoint we will target when getting the data from the server and when sending the updates to it. Note that we have set the port the Web API will be running on to 36830. When we get back to the Web API project, we will update the project settings so that we would be sure that it always uses this port.

Our service implements only two methods. getCities() that executes a GET request and returns the data from our database and commitCities() that makes a POST request to the server to send the changes we have made.

If you are implementing the scenario where you process the transactions inside the service and not on the server, replace the commitCities() method with the following:

What is happening above is we check if we have a transaction for each type of request and if we do — we push the corresponding request to the requests array. This guarantees that we would not send empty requests to the server.

We merge all possible requests into a single Observable so we can subscribe to it in our component and execute logic after all transactions are processed.

Now, when our service is ready, let us go back to the grid-batch-editing.component.ts file where we will utilize it.

First, import the City interface:

Find the addProductId property and delete it.

Next, change this line of code above:

with the following:

Next, navigate to the constructor and replace it with the following line:

Then navigate to the “ngOnInit()” method and update it like this:

Let us see what is happening here. On ngOnInit() we want to execute some initialization tasks. We subscribe to the cities() method of the CityService we injected in the constructor. When we get the response, we assign the received data (the actual data from our database) to the data property of the class. At this point, our grid would be populated with data.

We continue with the next functionality our application provides — to add a new record to the database. Navigate to the addRow() method. It provides a template for a new record. We would set the city properties to some meaningful defaults and after the user adds a new city to the grid, we would expect that he would update the fields. It is important to generate a random temporary ID for the new record when adding it to the grid as the transactions expect all the cities to have a CityID property. If, for example, we do not provide a value for this property, we will not be able to add more than a single new record as undefined would be set as value for the ID and when adding a second new row — it would find such unique ID already exists.

We also need to create the generateID() method. We would add it at the end of the code:

Have in mind this is a very simplified example of generating value. In real-life applications, you would like to implement a method that is more advanced as you do not want to have duplicated randomly generated values.

What is left in this file is to update the commit() method. This is where we will send updates to the server. The method should look like this:

Our grid component looks good now. However, as we made many changes to the grid, we should not forget to update the HTML markup as we have renamed a lot of properties.

Open grid-batch-editing.component.html and find the <igx-grid> element with id #gridRowEditTransaction. Replace it with the following:

If you look closer, you would see we are using a transformDates pipe in this code. You may learn more about pipes in Angular in this article. What we will use our pipe for is to transform the holiday dates that come from the server as strings to Date objects that IgxGrid can use.

So, let us create a new pipe. From the command prompt, execute the following command:

ng g pipe transformDates

This command would create a new folder named pipes inside your project’s app folder. Open this new folder and you would find that two files are generated inside. The first one, transform-dates.pipe.spec.ts is a file where automated tests testing the pipe would be added. There is even a predefined test scenario that tests if the pipe is initialized successfully. However, testing our application is beyond the target of our tutorial so we will take a closer look at the second file instead.

transform-dates.pipe.ts is where our pipe is actually implemented. Replace its content with the following code:

What this pipe does is transform the records we get from the server, changing the HolidayDatе value that is of type string to be a Date object. After the HolidayDate property of each record is updated, the pipe returns the transformed records and they are loaded in the grid.

Before we are ready to test it, we should update the app.module.ts file. Open it and add those imports (if you have created the service using the ng g command, the service would be automatically imported to the app.module.ts):

Next, add the HttpClientModule to the imports[] array. And finally, add the CityService to the providers array:

We are done with our client-side at this point. Now let us get back to the Web API project and make some little adjustments in order for it to work smoothly with the Angular project.

Open the Web API project in Visual Studio and right-click the CityService project. Click properties and the properties view for the project will open. Select “Web” from the menu on the left side and navigate to the “Project Url” field. Set it to http://localhost:36830/ and save the project (Ctrl + S). You may be prompted to create a virtual directory — accept it.

Build the project and re-run it with Ctrl+F5. Then refresh the Angular application and we would see the grid is loaded with data!

Oh! It does not look good… Open the development tools (F12) and navigate to the “Console” tab to see if an error message is available.

Access to XMLHttpRequest at ‘http://localhost:36830/api/cities/' from origin ‘http://localhost:4200' has been blocked by CORS policy: No ‘Access-Control-Allow-Origin’ header is present on the requested resource.

A CORS policy is blocking our request to the server. However, what is CORS at first hand?

Cross-Origin Resource Sharing (CORS) is a mechanism that uses additional HTTP headers to tell a browser to let a web application running at one origin (domain) have permission to access selected resources from a server at a different origin. A web application makes a cross-origin HTTP request when it requests a resource that has a different origin (domain, protocol, and port) than its own origin.

It makes sense now. Our Angular project is running on a different port than our Web API. It is a good thing that ASP.NET Web API 2 supports CORS! To enable CORS support we should add the Microsoft.AspNet.WebApi.Cors NuGet package to the project.

Right-click the CityService project and select “Manage NuGet Packages…”. When the NuGet Packages manager view is opened, select the “Browse” tab and search for Microsoft.AspNet.WebApi.Cors. Select the desired package and click “Install”.

When the “Preview Changes” dialog asks you to make changes to the solution, choose OK.

On the next dialog “License Acceptance” click “I Accept”.

After accepting those, the NuGet package will be installed.

Once this is done, expand the App_Start folder in your solution and open the WebApiConfig.cs file.

Add this using statement:

And add the following code to the Register() method:

Have in mind that this is the way to handle CORS if your controller is ApiController, like in our case. We should also add the [EnableCors] attribute to the controller itself. Add the following attributes to your controller:

Below the controller, add the following class:

If your controller was not ApiController, this would not work for you. You would need to set up CORS in the Web.config of the project.

A common issue you may face when you have several controllers in your project is to have CORS policies setup on both places — the Web.config and WebApiConfig.cs. If this happens, you would see an error like:

Access to XMLHttpRequest at ‘’’ from origin ‘’ has been blocked by CORS policy: Response to preflight request doesn’t pass access control check: The ‘Access-Control-Allow-Origin’ header contains multiple values ‘*, *’, but only one is allowed.

If you face such a case — make sure you comment out the section in your Web.config and set up your ApiController to handle the request.

At this point, we are ready to test our application. Fingers crossed! We are heading to the final section of our tutorial!

We are reaching the end of our tutorial on implementing the batch editing feature of the Ignite UI for Angular Grid! Thank you for sticking up with me in this pretty long publication! See you in the final step of this series. Stay tuned!

--

--