Implementing Server-Side Rendering in Angular using Route Resolve

Exploring the possibilities of Server-Side Rendering in Angular (v4) to enhance SEO performance.

Everything runs smoothly until the introduction of resolve on the route. The inclusion of resolve leads to the HTML title maintaining its original value when inspecting the source code.

Module Setup:

import {
  Injectable,
  ModuleWithProviders,
  NgModule
} from '@angular/core';
import {
  ActivatedRouteSnapshot,
  Resolve,
  Router,
  RouterModule,
  RouterStateSnapshot
} from '@angular/router';
import {
  Observable
} from 'rxjs/Rx';

import {
  ArticleComponent
} from './article.component';
import {
  Article,
  ArticlesService,
  UserService,
  SharedModule
} from '../shared';

@Injectable()
export class ArticleResolver implements Resolve < Article > {
  constructor(
    private articlesService: ArticlesService,
    private router: Router,
    private userService: UserService
  ) {}

  resolve(
    route: ActivatedRouteSnapshot,
    state: RouterStateSnapshot
  ): any {
    return this.articlesService.get(route.params['slug'])
      .catch((err) => this.router.navigateByUrl('/'));
  }
}

const articleRouting: ModuleWithProviders = RouterModule.forChild([{
  path: 'article/:slug',
  component: ArticleComponent,
  resolve: {
     article: ArticleResolver
  },
  data: {
    preload: true
  }
}]);

@NgModule({
  imports: [
    articleRouting,
    SharedModule
  ],
  declarations: [
    ArticleComponent
  ],

  providers: [
    ArticleResolver
  ]
}) export class ArticleModule {}

Component Implementation:

import {
  Component,
  OnInit
} from '@angular/core';
import {
  ActivatedRoute,
  Router,
} from '@angular/router';
import {
  Title,
  Meta
} from '@angular/platform-browser';

import {
  AppComponent
} from '../app.component';

import {
  Article,
} from '../shared';

@Component({
  selector: 'article-page',
  templateUrl: './article.component.html'
})
export class ArticleComponent implements OnInit {
  article: Article;

  constructor(
    private route: ActivatedRoute,
    private meta: Meta,
    private title: Title
  ) {}

  ngOnInit() {
    this.route.data.subscribe(
      (data: {
        article: Article
      }) => {
        this.article = data.article;
      }
    );
    this.title.setTitle(this.article.title);
  }
}

Navigating through Angular SSR is a learning experience, so any pointers or advice are welcome.

Answer №1

Retrieve your results from the snapshot instead of subscribing to route data, like shown below:

this.route.snapshot.data['article']

Make sure to register ArticlesService in the providers for the module as well.

Regarding imports, it's recommended to avoid using:

import {
  Observable
} from 'rxjs/Rx';

Instead, use the following import statement:

import {Observable} from 'rxjs/Observable';

Answer №2

After discovering that my main service was calling a secondary service to retrieve an authentication token using window.localStorage, I realized that accessing client storage led to Angular SSR omitting the generation of source code for my component.

A shoutout to Adam_P for guiding me through this issue!

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

The marker.js 2 documentation states that integrating marker.js with React poses compatibility issues when using next.js

I have followed the documentation for using this in my next.js app, but unfortunately, it's not functioning as expected. There are no errors, but nothing happens when I click on the image. It appears that this library may not be compatible with Next. ...

How to Dynamically Populate Textarea with Selected Checkbox Items using Angular 2

I'm having trouble with a list of checkboxes in a for loop. When I select one checkbox, the name should be displayed in a textarea. As I continue selecting checkboxes, their names should be added to the textarea. Similarly, when I deselect a checkbox, ...

How come this React DatePicker component is not appearing on the screen?

Check out this awesome component: import React, { Component } from 'react'; import DatePicker from 'react-datepicker'; class CustomDatePicker extends Component { constructor(props){ super(props); } render() { ...

Using the mt-downloader module in a Node application is a straightforward process

Hey there, I'm looking to incorporate the Multi downloader module into my project. I've checked out the GitHub link, but unfortunately, there are no examples provided on how to actually use this module. I came across this example and tried implem ...

Why does the second JavaScript form validation not function correctly when compared to the first?

Here is a form that I have created: <form action="next.html" id="userInput" method="post" onsubmit="return validate();"> Age: <input type="text" name="age" id="age"/> function validate() { var age = document. ...

Display the tooltip and highlight a specific pie slice when clicking on the legend of a pie chart in HighCharts

Hello everyone! I am looking for a way to display tooltips with legends on mouse hover and click events of a pie chart, similar to when hovering over pie slices. Additionally, I want the selected pie slice to slide out upon selection. Currently, I am usin ...

Problem with detecting collisions algorithm

Here is the jsfiddle I've been working on: http://jsfiddle.net/TLYZS/ Upon debugging the code and inspecting the collision function, it's evident that the collision is functioning properly when the user overlaps with the other character. However ...

State variable in Redux is not defined

While there have been numerous similar inquiries on this platform, I haven't been able to find a solution to my particular issue. Below is the React component in question: class MyTransitPage extends Component { componentDidMount() { this.pro ...

Choosing a table row in ReactIn React, you can

I am currently facing an issue with selecting only one row at a time in my React Material App. The problem I am encountering is that multiple rows are being highlighted instead of just one. My goal is to highlight/select only a single row at any given time ...

Leverage the router through the getServerSideProps method

My goal is to automatically redirect the user to the login page if their token has expired. I need to handle this in the getServerSideProps method where I make a request to the server for data. If the request is unauthorized, I want to use the useRouter ho ...

Searching for an array of strings in an express.js application

My concern is related to working with an array of strings. The specific situation involves: let search = ["user","country"]; In order to retrieve data from a MySQL database, I am looking to utilize the LIKE operator. An example of wha ...

Implementing a method to pass total value to the <td> tag in angular JS using controller

I am having trouble calculating the total IR for each table cell. Despite my efforts, the function is not working as expected and I can't figure out why. $scope.getTotalb = function () { var totalb = 0; for (var i = 0; i < $scope ...

Creating an undo feature for a dynamically generated checklist of checkboxes

I am using a combination of javascript/jquery and html to dynamically populate the page with checkboxes. When you click "add", a new checkbox is created. I am now looking for a way to add an undo button that would delete the last checkbox created. Here is ...

Making Angular2 Templates More Efficient with Array.prototype.filter()

I have a variable named networkInterface that includes an array called services. My objective is to create a checkbox input that indicates whether a specific service_id exists within the services array of the networkInterface. An illustration of JSON `int ...

How can I dynamically load a 3D model (in JSON format) at the current location of the mouse using Three.JS?

I'm currently working on a feature that involves loading a 3D model based on the mouse's position. Utilizing jQuery drag and drop functionality for this purpose has helped me load the model onto the canvas successfully, but I'm facing issues ...

Issue with Object.keys printing in an abnormal manner

My goal is to extract only the keys from an object, but instead of getting the desired output with the keys, I am seeing numbers. Here is the code snippet: data = {"property" : "{\"animalID\": \"12345\" ...

Leveraging async.js to perform in-depth population in sails.js

Facing a major challenge with my function in sails.js (v12). I am attempting to retrieve all userDetail using async (v2.3) for deep populating my user info: UserController.js: userDetail: function (req, res) { var currentUserID = authToken.getUserID ...

JavaScript's Math.round function does not always produce accurate results

After adding the specified line within the function, the code seems to encounter issues. parseLocalFloatCnt: num = Math.round(num*1.2); Is there a solution available for this problem? Your help is much appreciated. <!DOCTYPE html> <html> < ...

Move the footer down to the bottom of the page

I'm struggling to create a footer that consistently stays at the bottom of the page, regardless of the amount of content on the page. I've tried following various tutorials but haven't had much success. I'm starting to think I must be d ...

Using jQuery to target a specific HTML element by its ID, not requesting the entire webpage

Currently, I am attempting to utilize jQuery ajax to fetch a project page. In this scenario, the xhr variable is expected to hold the correct string to the webpage (the target page). I have set up a condition to prevent the page from loading as a mobile v ...