9

No Angular SPA without routing

 3 years ago
source link: https://devm.io/angular/tutorial-angular-spa
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

Angular Tutorial - Part 5

No Angular SPA Without Routing

25. Aug 2022


Efficient, simple, and scalable—that's how developing a web application should be. Since 2014, Google's Angular platform has been aiming to do just that. In this series, I’d like to introduce you to developing an Angular application and its concepts and best practices. They will be embellished with many code examples, tips, and tricks on how to achieve your goal of a maintainable web application with Angular.

The last two articles in this series successfully completed the topic of reactive programming using the JavaScript library RxJS. We learned what observables are and how we can subscribe and unsubscribe from data streams. For our application, unsubscribing is especially important. Otherwise, data will continue to be sent via the data streams, even long after our receiving component has been destroyed. We can also manipulate the data before it reaches our component with the help of pipeable operators like map and filter. For this, RxJS provides a whole set of transformation, filter, combination, and utility operators that help us develop with data streams.

Finally, we looked at the big topic of state management and stored our application’s title in a state. For this, we needed another construct from the RxJS library: the Subject Observables and Observers. This allowed us to store data from a component into the subject and receive the data again at another point with the data stream. We encountered the issue that simple RxJS subjects send data directly, regardless of if a component subscribes to the associated data stream. This can lead to timing problems when receiving the data. But the BehaviorSubject or ReplaySubject helps us handle the issue. Both subject types have the special feature of storing at least the last sent value and sending it again if a component subscribes to the data stream afterward.

In our application, we’ve already developed individual components for the list view and list item view. These are directly displayed when the application starts, as we’ve inserted our BookComponent into the AppComponent. In most applications, a user is taken to an overview area first rather than directly to a list display of assorted data. For implementation, we need a HomeComponent, which we’ll display first instead of the BookComponent.

> ng generate component home

This component should be part of the AppModule and exchanged with the BookComponent in the AppComponent template :

<app-header></app-header>
<app-home></app-home>

After recompiling, we notice that our book list is no longer displayed. To see both views in the applications, we can manually manipulate the browser’s DOM and keep adding a different component to the ViewContainer. But this principle has its weakness, mainly because of its complexity and that the state cannot be persisted. This is where the principle of routing comes into play. We call routing the loading of areas in the application depending on the state. The router is the service that manages the Angular application’s state. At runtime, it automatically exchanges the loaded components.

In this article, we want to make multiple views simultaneously available and implement a detailed view of a book with the help of routing. The user should be able to access all components with URLs, as we know from conventional web applications. Further clickable links are added to the application to help the user navigate our application.

Routing in a SPA

We can develop Single Page Applications (SPAs) with Angular. The concept of an SPA states that there is only one HTML page—the index.html page. Initially, this is empty, and all content is loaded into the page at runtime with JavaScript. When the view or page is changed, the page usually isn’t hard reloaded. Consequently, the index.html is loaded into the web browser at the beginning and is never reloaded during the session.

From a user experience perspective, this has some advantages. For instance, the user does not permanently see the page refresh when they interact with the application and only want to reload data from the backend. But at the same time, this idea leads to new challenges when navigating with the browser. For instance, how do you synchronize the browser’s BACK and FORWARD button navigation with the state of the application? Fortunately, all modern browsers implement the HTML5 History API. This provides a technical foundation for interacting with our Angular application using a service—the Angular router—to synchronize at runtime. As developers, we don't have to deal with the exact implementation and synchronization.

The following steps are needed to make the best use of the Angular router:

  1. Configure routes: each URL is assigned to a component
  2. Import the Angular routing module into our application
  3. Determine where our components should be displayed

It also makes sense to give the user buttons or clickable links that they can use to navigate to the URLs assigned to a component. This item isn’t included in the enumeration as it’s not mandatory for a successful routing implementation in an Angular application.

Configure routes

In our application, we want to display a specific view and a specific component, when a specific URL is called. This route definition contains the assignment of a URL to the component that will be displayed. In Angular, this is defined in an object:

const route = { path: 'home', component: HomeComponent }

The URL path is specified in the path property and the corresponding component in the component property. It’s important that the URL path is specified without a preceding slash. Once we call our application with the URL localhost:4200/home, the HomeComponent component is loaded. Usually, there’s more than one route in an application. We’ll create these in an array. For this, the Angular package @angular/router provides us with a corresponding data type (Listing 1).

Listing 1

import { Routes } from '@angular/router'


const routes: Routes = [
  { path: 'home', component: HomeComponent },
  { path: 'about', component: AboutComponent },
]

Once all the routes are defined and the components are mapped to them, we need to register the array in our application. Routes are defined centrally and apply to a feature in the application. Currently, our application has two features: app and book. We’ll take a look at how the route definition is divided by features a little later in the article. For now, all routes are registered in AppModule (Listing 2).

Listing 2

import { HomeComponent } from './home/home.component';
import { RouterModule, Routes } from '@angular/router';


const routes: Routes = [
  {path: 'home', component: HomeComponent},
]


@NgModule({
  declarations: [...],
  imports: [
    ...
    RouterModule.forRoot(routes),
  ],
  bootstrap: [ AppComponent ]
})
export class AppModule {
}

We’ll register our route definitions using the imported RouterModule from the @angular/router package. A lot of routes are defined in an Angular application and our AppModule gets bigger as the array grows. As a result, it’s considered best practice to create an extra mini-module that’s used for defining the routes of a feature (Listing 3).

Listing 3

import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { HomeComponent } from './home/home.component';


const routes: Routes = [
  {path: 'home', component: HomeComponent},
]


@NgModule({
  imports: [RouterModule.forRoot(routes)],
  exports: [RouterModule]
})
export class AppRoutingModule {
}

This way, we remove all imported data types and route definitions from our AppModule and only import the AppRoutingModule. This looks a bit awkward at first, but it makes sense at second glance. The AppRoutingModule mini-module creates a self-contained routing with our self-defined routes and makes this module available to the outside. The advantage of this procedure is that the routing’s entire configuration with all necessary dependencies is encapsulated in the mini-module. The Angular CLI already lets you generate an AppRoutingModule when creating a new Angular project (Fig. 1).

Bild1.png

Fig. 1: Creating AppRoutingModules

Alternatively, we can use the --routing option when creating the project. With the help of routing, we want to navigate to different views of our application. We’ve already defined the route for our HomeComponent. For our second step, we need another route for the BookComponent:

const routes: Routes = [
  { path: 'home', component: HomeComponent },
  { path: 'book', component: BookComponent },
]

But what if the user doesn’t address a specific route, the root route with the root URL /? To provide the application with this info, we’ll also need to create a route definition for the URL:

const routes: Routes = [
  { path: '', redirectTo: '/home' pathMatch: 'full' },
  { path: 'home', component: HomeComponent },
  { path: 'book', component: BookComponent },
]

The specified path is empty. So, the root URL should be assigned there. Apart from that, we have the option of either displaying a component or redirecting to another URL. In this example, that would be /home.

The pathMatch: 'full' property has also been added. This way, we specify that this route only applies when / is called, but not when the URL is simply a prefix of another.

Now our applications have registered all important routes. One small problem that we may encounter is if a component isn’t displayed if a user enters the wrong URL. The best practice here is to create a PageNotFoundComponent and display it for every route that hasn’t already been assigned to another component.

const routes: Routes = [
  ...
  { path: '**', component: PageNotFoundComponent },
]

You can specify...

</div


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK