Instructor: In this video, we want to build a to-do app with Angular which gets synchronized by SignalR and has an ASP.NET Core backend. Let's take a look at our backend first.
In our startup.cs file, we are adding Cores and SignalR to our services. Please, do not use that Core setting in production. This is just for demo purposes. If we scroll down a bit, we are also adding the Cores policy and SignalR to our pipeline.
With SignalR, we are mapping a route called /to-do-app to to-do-app-class. Let's take a look at the class next.
As you can see, the class is empty, because we are not invoking that help methods directly from the client -- which we could here -- but we are sending out the events from the backend over the controller as a reaction to POST and PUT requests.
Here, we are using a dictionary as a data store, and we are injecting the IHubContext context interface from SignalR to the constructor to send out messages to our Angular client. If we post something, we will send the event called itemAdded. If we update something, we will add the event called itemUpdated. Our class to-do item is just a pull call having some basic fields like ID, value, and done.
Let's start with the client. The client is a new Angular 6 CLI scaffolded project. The first thing we need to do is installing the npm package of SignalR by opening up a console and typing npm install @aspnet/signalr.
Having done that, we can add a class representing our to-do class on the server, adding a new folder, and a new file called to-do.model.ts and adding the properties. The next step is to build an Angular service, which encapsulates the SignalR communication, adding a new folder called services and a new file, signalr.service.ts.
First, let's build the connection. We can import the SignalR package with ES 6 imports, adding a private variable called connection. In the constructor, we can add HubConnectionBuilder with a URL to build up the connection.
After calling build, we get back the HubConnection from SignalR. Now, let's register on the event itself.
We are adding methods if particular events happen on the connection, and are just logging them out. If the server sends the event item added, we are jumping in that method, and the same with itemUpdated on the itemUpdated event.
Let's add the possibility to tell others that these events happened using a subject, which we can invoke with next. We are adding two subjects under the class called itemUpdated and itemAdded and invoke them with next in our particular methods.
Of course, we need to make that service injectable in our rootScope, so we are providing it in root. Last but not least, we are calling the method to register on the events we just created, and start the connection in the end with catching the errors in case one happens.
Let's head over to our component. All we need now is to inject the SignalR service into our constructor and the HTTP service as we want to fire GET, POST, and PUT calls to our API. Let's subscribe to the events now we just created in the SignalR service.
If an item got added, we are pushing it into array of items, and for the sake of simplicity, if an item got updated, we just delete the old one and replace it with the new one.
In the OnInit method, we will do an initial GET call to get all the items from the API if there are some already, and we do initialize our array with the existing items.
We also want to have a form where people can add to-dos. The form has only one input called to-do value. If a to-do gets added, we can add a method called @to-do, which gets the value of the form, creates a new object which we can send over the wire, and posting it back to our backend then. After this, we are just resetting the form.
Also, when marked as done, we want to update our item with a PUT call to our backend. We are setting our item to done and PUT it over HTTP to our backend afterwards. To make this work, we have to import the Reactive Forms module and the HTTP client module in our NG module imports.
As a last step, let's build the UI, which is very simple. We are just adding a form, which has the input we just created and a button which is disabled if the form is invalid. On submit, we call the add to-do method.
Underneath that, we build a new div with an unordered list. We are iterating over the items, and if the item is done, we display it in a stroked tag with a class called inactive. Otherwise, we are just displaying it normally.
Another button for each item calls the method markAsDone to set the item to done, and firing a PUT request to the backend, and receiving a SignalR event afterwards. Let's shortly create this CSS class for inactive. It's just setting the color to gray, nothing spectacular here.
Let's start the client now and start the server too. On the left-hand side, we can call npm start to start the Angular application. On the right-hand side, we can start our ASP NET Core server with .net run.
I just took two browsers consuming the same application. If we now type something into the left hand browser, it gets automatically displayed on the right hand side. Also, we can mark it as done, and it also works the other way around.
This is one way how you can push events from the server side into your Angular application without reloading the page with Angular and ASP.NET Core SignalR.