<button (click)="GetTodos()">Get Todos</button>
now when we open our app we should see a blank page with a button named saying Get Todos, and we can't test our API yet because simple we don't have our server running, so lets do just that:
Open a new terminal window by clicking on the "+" icon
Cd to the API folder and execute
dotnet watch run
Wait till the server is open and go to our Client interface, open the Console and press the Get Todos Button, you should see something like this:
we get an error, and if we dive into it we could tell that the Access has been blocked by CORS policy, which means that our API does not have a policy to accept requests from our client (if you want to deep dive into CORS I would suggest this article). So lets make our API accept requests from this client, go to Startup.cs in our API solution and add the following snippet into our ConfigureServices method first create the variable holding the name of our policy, place this on the very top of the Startup class :
readonly string MyAllowSpecificOrigins =
"_myAllowSpecificOrigins";
and then modify the ConfigureServices method:
services.AddCors(options =>
{
options.AddPolicy(name: MyAllowSpecificOrigins,
builder =>
{
builder.WithOrigins("http://localhost:4200/")
.AllowAnyHeader()
.AllowAnyMethod()
.AllowCredentials()
.SetIsOriginAllowed((host) => true);
});
});
and then go to our Configure method and add this line :
app.UseCors(MyAllowSpecificOrigins);
now our app should be working fine, so let's test it again:
and we got our response, now let's display that response in the UI, for this we first need to create a variable holding our response, let's call it
todos, create that variable in our
app.component.ts and then we should modify the return type of our get method from our service and our component.
Let's start with our service, basically we will almost change everything to make it look like this :
GetTodos() {
return this.http.get(this.url,{
observe: 'response',
}).pipe(map((response) => {
return response.body;
}));
}
we modified our method so we're dealing with observables which is the best option when it comes to passing values. And then lets move to our GetTodos method that is in our component and replace it with the following, and lets add a Console.log() statement to verify that everything is fine, you'll understand what I mean in a second :
GetTodos(){
this.service.GetTodos().subscribe(data =>{
this.todos = data;
console.log(this.todos);
});
}
in now that the return type of the GetTodos from the service is an observable, we will subscribe to that and get the data and pass it to our todos variable that we created and then we log that, so let's see what we get :
and there we go our response is what it's supposed to be, now lets display these in our web app, we will add this simple angular syntax into our
app.component.html (you should've learnt this syntax in the free course I mentionned or on your own) :
<ul>
<li ngFor="let todo of todos">{{todo.content}}</li>
</ul>
Now let's test our app and voila :
our html is displaying what we get from our response. now let's make a simple post request, we will add a simple form with a button called Add Task, the html for that is the following :
<input type="text">
<button>Add Task</button>
now let's add a variable in our app component that will hold the content of the input, lets call it content and let's use angular syntax to two-way bind the input with that variable, the new input should look like this :
<input type="text"
[(ngModel)]="content"
[ngModelOptions]="{standalone: true}">
you should see errors if you just copy pasted that part into your app, because here you need to go app.module.ts and into the imports array add a reference to FormsModule the new array should look like this :
imports: [
BrowserModule,
HttpClientModule,
FormsModule
]
now what is left is to create our post method, so let's head to our service again and create the required method, but we know that in our POST request there are headers that we need to pass, so lets create a variable called headers of type HttpHeaders and pass it some values, like the following :
headers = new HttpHeaders().
set('Content-Type', 'application/json');
and then lets create the method that should look like this :
PostTodo(todo){
this.http.post(this.url,todo,{
headers : this.headers,
}).subscribe(response =>{
console.log(response);
});
}
as you can see, the method requires a parameter which is a todo, but what that that to do is, it is simply an object that we will create in a while, then we will pass that todo to our POST request, in the body, and you probably wonder where that content will be coming from, and the answer is that we will get from the value of our input, so let's do that, go to our app component, first create a folder called Models in src>app and inside of it create a new file called and name it Todo.ts then we will declare a class inside that file which should look similar to what we do in C# except it is prefixed with export and then we add some properties to it and it should look like this :
export class Todo
{
id:number;
content:string;
}
as you can see, we got some properties, id and content which is what is required from us to send to the api, now let's head to our app.component.ts and create the PostTodo method :
PostTodo() {
let todo = new Todo();
todo.content = this.content;
if (todo.content) {
this.service.PostTodo(todo);
}
setTimeout(() => {
this.GetTodos();
}, 1000);
}
basically we created an instance of our Todo object, then we're passing the values from our input box to its content property and we are checking if the content is not null, if so we send the request, if not we do nothing, and after sending the POST request , we will resend the GET request in order to update the displayed data, but we are waiting one second (1000ms) before we do that, so our app has the time to complete the request, I took this approach for the sake of simplicity but you can go further than that and make it more responsive on your own but for now this is enough, so now lets make hitting the Add Todo button performs the method we just created it and lets test it, the new method syntax should look like this:
<button (click)="PostTodo()">Add Task</button>
and now let's test our client, type the task content in the input box and click Add Task :
as you could see our third task has been added to the database successfully, now the last thing to do is implement the DELETE request, for that we will need to add a delete button on the side of every task, so we need to modify the current html into something like this :
<ul>
<li ngFor="let todo of todos">{{todo.content}}
<button>Delete</button>
</li>
</ul>
now let's create the Delete method, let's head on to our service and create the following method,
the code here explains itself, we are required to pass the id of the object, then we build the new URL with that id, and we send the DELETE request to that URL, now let's head out to our app.component.ts and create the DeleteTodo function there as well, and it should look like this :
we are required once again to pass and id parameter and then pass that same id to our service.DeleteTodo() method, how will we get that id param you wonder ? the asnwer is simple :
Now your app is technically Finished all what is left is to test the Delete method :
and voila, Congratulations on this milestone, you created your first functional full-stack app, hope this is the beginning of a successful programming career for you.
HOMEWORK
Now that you've learned how to use Angular, you will need to do your researches and figure out a way to modify existing tasks, to help you out I will give you some hints and an example to start,
Hints
Hint 1 : the Request type of this method is called PUT
Hint 2 : the method will receive 2 paramaters (int id, Task task)
Hint 3 : Display the tasks in a form instead of a label, modifying that form and hitting the update button will update the task
Example :
Also the app right now looks ugly, so try to style it and send me what you've done either on my socials or via the contact form, and the best one will get featured here.
After you finish doing the exercise, visit My GitHub Repo and compare my code to yours
Final Words :
Congratulations again, you have completed your first full-stack web app, you're now in the programming game, and always remember that constantly learning is the way to succeed, there's still a long journey ahead of us because I'm still learning as well good luck for us and especially for you and hope you kickstart your programming career