Categories
Angular HTML Javascript Projects Typescript

Easily create custom Typescript interfaces with quicktype.io

I am sure you, as a web developer, have faced a lot of times the problem of having to deal with complex Objects in your Typescript or Angular projects. One way to do it is creating our custom Typescript interfaces or classes, but it could give us a lot of work when, as said, the objects are too complex . We will see in this article how to create our Typescript interfaces using a powerful tool called Quicktype.io . This tool can be accessed through the website but also as a Visual Studio extension.

Probably many of you are experienced developers who know the benefits of Typescript interfaces and custom types much better than me, but the point here is, among everything, how to use quicktype.io to deal with big Objects, and to make an interface for those big Objects in less than a minute even if they have dozens of properties.

First of all, we will see a piece of code which shows us one typical response returned by an HTTP request in Angular, from the Giphy API. I am currently developing an app which uses Giphy API to show images, among other functionalities, and I will use some pieces of code to show you how to use it and the great advantages of creating your custom Typescript interfaces.

This time, as it is a long code, will just link it and not embed, for readability reasons:

https://gist.github.com/Franweb79/58671911ea12b583adc7712efb82d369

As you can see, it is an Object with a lot of properties, nested ones… it is easy to have errors trying to access those properties, and is very difficult to trace a path to one nested property, you could have mistyping errors…

Advantages creating custom Typescript interfaces

With Typescript interfaces, we will be able to avoid the errors mentioned above more easily, taking advantage of the help that Typescript can give us to access an Object and its properties.

Not only that: as mentioned above, with Quicktype.io we will be able to create our Typescript interface for such complex Objects fast and easily.

Let´s imagine we will request 10 items from Giphy with our HTTP request. The limit of items can be as a query parameter, as we will see later. Please read Giphy documentation to know more about it.

The result will be a very big Object with thousands of lines. But it doesn´t matter. Let´s see the code. First we will intentionally use a typical bad practice to request data, using the “any” types.

Bad way of requesting data: using “any” type

This would be our HTTP request. The ApiData property is where we will store our data to be shown in the template.

As you can see we have declared a variable called wholeQueryString where we can set the limit of items we want to request. To see more info about the other parameters I recommend you again to visit Giphy for Developers documentation.

  let wholeQueryString:string=`${URL}${Key}&limit=10&q=${searchQueryParameter}`;

Also we have set the property and the parameter for the HTTP request as “any”. Sometimes developers use this to avoid Typescript throwing errors. For example, when we do

 this.APIdata=response.data;

If we don´t declare the response as “any”, Typescript will say something like “ey, this is a generic Object type, I can´t see a data property inside because it is not part of a generic Object type”.

image to show typescript error when not using proper typescript interfaces, but the any type

We can solve it by setting the response as “any”, it is like telling Typescript: “Is OK, I know what I am doing, just let me do”. Then it won´t complain:

image to illustrate a bad way to fix error with the any type

But this way, we must know our response Object structure; we must check the properties and know our response has a data property. That can get worse if we must access something like

response.data[0].url

As mentioned above, it is easy that you have errors trying to follow complex, nested property paths.

It is a solution, our software will work; but is not the best way to do it.

Using quicktype.io to create our Typescript interfaces

Let´s create then our custom Typescript interface, see how it helps us, and how to create it with quicktype.io

If you know something about Typescript interfaces, you can figure out how hard it would be to build our interface for an Object as we get on this Giphy response, isn´t it? Imagine you have to check more than 20 properties, declare types… and same for nested Objects.

Fortunately we will use quicktype.io to do that now.

First we run our HTTP code.

As we have a

console.log (response);

It will show us the complete Object that Giphy returns.

image to illustrate an object returned by angular HTTP request

We just copy the entire Object and paste it inside the left panel of quicktype.io. It will transform our JSON Object into typesafe code in any language, including Typescript.

Remember to copy the entire Object, just right-click over it and select “copy object”, works the same for Firefox and Google Chrome.

You must write a name for your Typescript interfaces, in this case we will use GiphyResponse. Then, in the options button you can select the language you want the JSON to be parsed. In our case it is Typescript.

image to show how to parse a JSON into custom Typescript interfaces

And that’s it! We have a complete interface of our long response in less than one minute!

Using the quicktype.io generated data for our projects

Now that we have the code, we just can copy and paste it to create our own Typescript interfaces inside our Angular project.

First we will create a file called

giphy-response-interfaces.ts

Preferably do it inside an “interfaces” folder. Just copy the code generated by quicktype.io

Now we are ready to use our custom Typescript interfaces wherever we need inside our project. And now, we will use it to handle Objects easily with the help that Typescript can give us.

We will change the “any” types we have written before, with our new custom type, GiphyResponse, or derived ones.

We can see our interface has now image to show structure generated for our custom Typescript interfaces The relevant data we need, as its own name says, will be inside the “data” property.

Remember we will store our data inside a property. As we see, the data is an array of Datum type, so we change:

 public APIdata:any;

to

 public APIdata:Datum[];

As it is an array, we can initialize inside the constructor it simply as:

   this.APIdata=[];

Now we must change the HTTP response code. So you can replace this:

for this:

Apart from the type change we have done for the property, we can see we changed two things inside the HTTP request:

 this._http.get<GiphyResponse>
  • Now the response parameter has also our custom type. Please note that it would now work even just leaving the response without type:
next: (response)=>{

        this.APIdata=response.data;

       

        console.log (response);

      }

But I humbly think it is a better idea to specify this response with our custom type

next: (response:GiphyResponse)=>{

        this.APIdata=response.data;

       

        console.log (response);

      }

Well, and where is the advantage of all of this?

Look what happens now:

gif image to describe advantages of using custom Typescript interfaces

Yes! Now Typescript knows the structure and property of the Object, thanks to our custom Typescript interfaces. We have told Typescript something more specific and well described than a vague “any” type so it can help us.

The best advantage is that, if we have to access now to any nested property inside the object, we can do it much more easily, with Typescript safely guiding us through the structure of the Object.

Look at this. Remember data property is an array, so we could do, for example, for first element of the array:

second GIF to illustrate how to navigate through an Object with custom Typescript interfaces and types

You can see all nested properties, objects… much easier than exploring the browser console and following the paths by yourself, right?

I hope this article was useful for you. Remember to check other Angular or Typescript related articles we have written.

 

Image by James Osborne found in Pixabay

Categories
Angular HTML Javascript

How to disable events in Angular

Sometimes we have an event bound to an element and for any reason we have to avoid that this event is triggered, so we have to disable that event. To do such tasks, in vanilla Javascript we have a method like preventDefault(). We will see how to disable events in Angular.

You can find more info here:

https://www.w3schools.com/jsref/event_preventdefault.asp

The way to accomplish this with Angular is very similar, and we can do do it through the $event object. This object contains information about an event, and it has properties like $event.target to reference the element which triggered the event. You can find more info about Event Binding in angular  here

The way to pass the event as a parameter to a method would be like this:

<button (click)="showModal($event)">Push button</button>

So, if we want to prevent that this click event is not triggered, all we have to do is using the preventDefault() method, this way:

<button (click)="showModal( $event.preventDefault() )">Push button</button>
 Example to apply what we have learned

We will see more clearly with this example.

Let´s assume we have a search bar. When we click on this bar, we will show the search history made by this user. Each element of this list will have some styles added to tell the users they can click the element to perform a new search with this text. It would be something like this:

software behavior to ilustrate how to disable events in angular

But, what if the search is empty? We will show a text to invite the user to enter a valid search. We will use the same HTML element we have to show the search history, but of course, this time, the element should not be clickable, because it is not a part of our search history. Something like this:

software behavior 2. Another example to show how to disable events in Angular.

As we see, “please enter valid search” has different styles and we have prevented the click event from being triggered. Nothing will happen if the user clicks on it.

How have we done it with Angular? This is the piece of code:

<ul class="d-flex flex-fill navbar-nav mb-lg-0">

  <li class="w-100">

    <input class="form-control me-2" type="search" placeholder="Search Gifs..." aria-label="Search" (keyup.enter)="search($event)" (click)="displaySearchHistory()" #searchInputElement>

    <ul id="search-history"  [@openClose]="isOpen ? 'history-open' : 'history-closed'" >

       <span *ngIf="isClickable;else enterValidSearch">

         <li class="clickable-list" *ngFor="let item of this._gifsService.historicObserv$ | async" (click)="search($event)">

            {{item}}

         </li>

       </span>

       <ng-template #enterValidSearch>

         <li (click)="$event.preventDefault()">Please enter valid search</li>

       </ng-template>

    </ul>

 </li>

</ul>

Note: There are parts of the code which are beyond the scope of this article and have nothing to do with how to disable events in angular, since I used things like Angular animations to apply smoother transitions when we show the list. If you want details about Angular animations check official examples here. Also you can see we used Observables and async pipe to show data. I recommend you to see this article to know a bit more about it.

Also the code we used on displaySearchHistory() and search() methods, or to validate if a search is empty or not, will not be detailed here. Many times angular forms are used to do those kinds of validations, but I used plain Javascript. The trim() method was very useful to accomplish it 🙂

The important things we must focus here are the (click) events, and the $event object.

What we did here is validate against a boolean property called isClickable if we will allow the click event to be triggered or not.

In the case isClickable is true, a <li> HTMLelement with the search history will be shown. Notice we will apply a class called "clickable-list" to show some styles when we hover over the result. Just in case you are curious, my css rules are:

.clickable-list{

    /*

        to make each LI element fill all the width of the UL element. As we can see on browser´s console

        it has a padding-left of 2rem, we adjust the margin left as the same negative value.

        The padding left here is to move the text a bit

    */

    margin-left: -2rem;

    padding-left: 2rem;

}

.clickable-list:hover{

    background-color:#FFC107;

    color: white;

}

As we said before, we will be able to control our (click) event and pass it to the search() method with the $event object as parameter. That is why we have written (click)="search($event)"

 <span *ngIf="isClickable;else enterValidSearch">

     <li class="clickable-list" *ngFor="let item of this._gifsService.historicObserv$ | async" (click)="search($event)">

         {{item}}

     </li>

 </span>

With this object we will be able to perform several operations we will need on our code.

But in the case isClickable property is false, we will show a different <li> element. This time, as we said, no operation can be triggered when the user clicks this element. The way to prevent this is using angular ng-template element. With a template variable called enterValidSearch we will reference this template on the *ngIf statement and will show it in the case isClickable is false (that will be validated in our .ts code and, as said, is beyond the scope of this article).

<ng-template #enterValidSearch>

    <li (click)="$event.preventDefault()">Please enter valid search</li>

</ng-template>

Also we can see we can prevent (click) event from firing with $event.preventDefault()

And that´s it! I hope this article is helpful to learn how to disable events in Angular. Please contact me if you see any errors or things I could improve.

*Featured image by Gerd Altmann found in Pixabay

Categories
Angular HTML Javascript

Angular and Observables: how to avoid the subscription with the help of Async Pipe

If you have been using Angular for a while, probably you have met and used the Observables. Observables are part of a paradigm called Reactive Programming, and are included in Angular with the rxjs library. As you can read on the links, Reactive programming and Observables help you work with asynchronous data streams.

You can read more info about Observables in this excellent article

As you can see there, in order to be able to use the Observables, you have to subscribe to them. Subscribing is like calling a function, or invoking the Observable, then you can see the results produced by the Observables.

But when you are using an Observable and want to show the data emitted by the Observable on your component´s template, you can avoid the subscription and, thus, a good amount of logic and code. That is possible with the Async pipe.

It unwraps a value from an asynchronous primitive so you can apply it on the observable and get its result without any subscription.

Let´s see it with a simple example

We have a regular angular component where we have defined an array of numbers and an Observable. The only thing we will do is, create an Observable from that array, and then we will use the Async pipe in the component´s template to show the results.

To create the observable we will use rxjs operators. In this case we will use the of( ) operator

With an array, the of( ) operator emits the whole array at once as an observable, then we can iterate over it and apply the Async pipe.

For more info about this operator and the difference with another commonly used operator to generate observables ( from( ) ), please check following links:

Enough talking, we will see the code:

 

observables-test.component.ts

import { Component, OnInit } from '@angular/core';

import { Observable, of } from 'rxjs';

@Component({

  selector: 'app-observables-test',

  templateUrl: './observables-test.component.html',

  styleUrls: ['./observables-test.component.css']

})

export class ObservablesTestComponent implements OnInit {

  
 //Observable should have same type as the array, in this case, number[]
  public observableWithAsync$:Observable<number[]>;


  //this array will be passed to the observable using the of() operator

  public arrayToBePassed:number[];


  constructor() {

    this.observableWithAsync$=new Observable();

    this.arrayToBePassed=[0,1,2,3];

   }

  ngOnInit(): void {

    this.observableWithAsync$=of(this.arrayToBePassed);  


  }

}

If you want to know about the differences between the constructor and the ngOnInit, please read this useful link.

Summarizing:

Mostly we use ngOnInit for all the initialization/declaration and avoid stuff to work in the constructor. The constructor should only be used to initialize class members but shouldn’t do actual “work”.

So you should use constructor() to set up Dependency Injection and not much else. ngOnInit() is a better place to “start” – it’s where/when components’ bindings are resolved.

 

Also you could note, I created the Observables using a $ at the end. That has a reason:

https://stackoverflow.com/questions/37671700/angular2-style-guide-property-with-dollar-sign

OK, once we have created the Observable, all we have to do to use it on our template is this:

observables-test.component.html

<ul>

    <li *ngFor="let number of observableWithAsync$ | async">

        {{number}}

    </li>

</ul>

Now, we see all we have to do is iterating over the observable and apply the Async pipe. Output on the screen will be:

This way we will avoid subscriptions and will certainly simplify our code.

Image provided by Luisella Planeta Leoni LOVE PEACE 💛💙 en Pixabay