Using SignalR with Angular

Using SignalR with Angular

In a previous blog post, we discussed how to create real-time web applications using SignalR and React. If you have already gone through that, you would know the magic of SignalR in pushing instant updates, allowing users to receive data in real-time. In this post, we’re going to apply the same concept but with Angular.

Setting Up the Server with SignalR

Just as a quick refresher, SignalR provides an easy method to communicate between the server and the client in real-time. We start by installing the appropriate NuGet package:

Install-Package Microsoft.AspNet.SignalR

The hub, as described before, acts as the communication centre. Here’s an example of how we set up a basic hub:

using Microsoft.AspNet.SignalR;

public class ChatHub : Hub
{
    public void Send(string message)
    {
        Clients.All.broadcastMessage(message);
    }
}

With SignalR, we can either broadcast a message to all connected clients:

Clients.All.broadcastMessage("This message goes to everyone!");

Or, target a specific client using its unique connectionId. The connectionId plays a crucial role in sending tailored messages or performing client-specific operations.

SignalR meets Angular

Now, let’s pivot towards the client-side of things. There’s a package for this:

npm install @microsoft/signalr

Let’s now illustrate an Angular component that actively listens for and displays SignalR messages:

import { Component, OnInit } from '@angular/core';
import * as signalR from '@microsoft/signalr';

@Component({
  selector: 'app-signalr',
  template: `
    <div>
        <p>{{ message }}</p>
    </div>
  `
})
export class SignalRComponent implements OnInit {
  connection: any;
  message: string;

  ngOnInit() {
    this.connection = new signalR.HubConnectionBuilder()
                        .withUrl("/chatHub")
                        .build();

    this.connection.start()
                   .then(() => console.log('Connection started'))
                   .catch(err => console.log('Error while starting connection: ' + err));

    this.connection.on('broadcastMessage', (receivedMessage: string) => {
      this.message = receivedMessage;
    });
  }
}

In this example, we’ve built an Angular component that sets up a connection to our SignalR hub, listens for a broadcastMessage, and then displays that message.

If you’re thinking of capturing different messages in different components, the concept remains similar. Create multiple components, and in each, set up a SignalR connection that listens for its respective message:

// Component A
@Component({
  selector: 'app-component-a',
  template: `
    <div>
        <p>{{ messageA }}</p>
    </div>
  `
})
export class ComponentA implements OnInit {
  // ... rest of the code remains mostly the same
  // Just ensure that you're listening to the 'messageForA' in this case.
}

// Component B
@Component({
  selector: 'app-component-b',
  template: `
    <div>
        <p>{{ messageB }}</p>
    </div>
  `
})
export class ComponentB implements OnInit {
  // ... similar structure
  // Listen to the 'messageForB' for this component.
}

Obtaining ConnectionId in Angular

As we covered in the React example, you can obtain the connectionId on the client side by invoking a method on the hub. The same logic applies for Angular:

ngOnInit() {
  this.connection.start()
                 .then(() => {
                   console.log('Connection started');

                   // Get the connectionId after successfully connecting
                   this.connection.invoke('GetConnectionId')
                                  .then((id: string) => {
                                    console.log("ConnectionId is:", id);
                                    this.connectionId = id;
                                  })
                                  .catch(err => console.error(err));

                   // ... set up other SignalR event handlers here ...
                 })
                 .catch(err => console.log('Error while starting connection:', err));
}

Remember to add a connectionId property to your Angular component to store and potentially display the value and there you have it.

Suleyman Cabir Ataman, PhD

Sharing on social media:

Leave a Reply