Blog Series: Building a Single Page Application (SPA) with Angular and Rails (Part 5)

Raghavendra S
2 min readDec 20, 2024

This 6-part blog series takes you through building a single-page application (SPA) using Angular for the frontend and Ruby on Rails for the backend. By the end of this series, you’ll have a fully functional SPA and understand the integration of these two frameworks.

Part 5: Building a Reactive SPA

Step 1: Use Angular Reactive Forms for Dynamic Inputs

Reactive forms provide a powerful and flexible approach to handling form input and validation in Angular. First, import the ReactiveFormsModule into your application module.

Update app.module.ts:

import { ReactiveFormsModule } from '@angular/forms';

@NgModule({
declarations: [
// other components
],
imports: [
ReactiveFormsModule,
// other modules
],
bootstrap: [AppComponent]
})
export class AppModule {}

Step 2: Create a Reactive Form for Articles

Update ArticlesComponent to include a form for creating articles:

import { Component, OnInit } from '@angular/core';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { ArticleService } from '../services/article.service';

@Component({
selector: 'app-articles',
templateUrl: './articles.component.html',
styleUrls: ['./articles.component.css']
})

export class ArticlesComponent implements OnInit {
articles: Article[] = [];
articleForm: FormGroup;

constructor(
private articleService: ArticleService,
private fb: FormBuilder
) {
this.articleForm = this.fb.group({
title: ['', Validators.required],
content: ['', Validators.required]
});
}

ngOnInit(): void {
this.articleService.getArticles().subscribe(data => {
this.articles = data;
});
}

createArticle(): void {
if (this.articleForm.valid) {
this.articleService.createArticle(this.articleForm.value).subscribe(newArticle => {
this.articles.push(newArticle);
this.articleForm.reset();
});
}
}
}

Update articles.component.html to include the form:

<form [formGroup]="articleForm" (ngSubmit)="createArticle()">
<label for="title">Title</label>
<input id="title" formControlName="title">

<label for="content">Content</label>
<textarea id="content" formControlName="content"></textarea>

<button type="submit" [disabled]="articleForm.invalid">Create Article</button>
</form>

<div *ngFor="let article of articles">
<h2>{{ article.title }}</h2>
<p>{{ article.content }}</p>
</div>

Step 3: Add Real-Time Updates with Rails ActionCable

Install actioncable in your Angular app:

npm install @rails/actioncable

Create a CableService to manage WebSocket connections:

import { Injectable } from '@angular/core';
import * as ActionCable from '@rails/actioncable';

@Injectable({ providedIn: 'root' })
export class CableService {
private cable = ActionCable.createConsumer('ws://localhost:3000/cable');

subscribeToArticles(callback: (article: any) => void): void {
this.cable.subscriptions.create('ArticlesChannel', {
received: callback
});
}
}

Update ArticlesComponent to include real-time updates:

constructor(
private articleService: ArticleService,
private cableService: CableService
) {
// other code
}

ngOnInit(): void {
this.articleService.getArticles().subscribe(data => {
this.articles = data;
});

this.cableService.subscribeToArticles((newArticle) => {
this.articles.push(newArticle);
});
}

Create a Rails ArticlesChannel:

rails generate channel Articles

Update articles_channel.rb:

class ArticlesChannel < ApplicationCable::Channel
def subscribed
stream_from 'articles'
end
end

Broadcast new articles in the ArticlesController:

def create
article = Article.new(article_params)
if article.save
ActionCable.server.broadcast 'articles', article
render json: article, status: :created
else
render json: article.errors, status: :unprocessable_entity
end
end

We will learn about deploying in the next part ..

Sign up to discover human stories that deepen your understanding of the world.

Free

Distraction-free reading. No ads.

Organize your knowledge with lists and highlights.

Tell your story. Find your audience.

Membership

Read member-only stories

Support writers you read most

Earn money for your writing

Listen to audio narrations

Read offline with the Medium app

Raghavendra S
Raghavendra S

Written by Raghavendra S

Artificial enthusiast. Rubyist.

No responses yet

Write a response