# Display real-time data in Angular

Source: https://tpiros.dev/blog/display-real-time-data-in-angular

Two ways to push real-time data into an Angular application. One uses sockets. The other leans on the `AsyncPipe` and Observables. Both get the job done, but they feel very different to build.

# Setting the scene

Most Angular apps follow a familiar pattern. A component calls a service, the service calls an API, data comes back, and the template renders it. Simple enough.

But what happens when that data changes constantly? Think stock tickers, live radio displays showing the current artist and song, or any feed that refreshes every few seconds. You need a way to keep the component in sync with whatever the API is sending.

# Async Pipe & Observables

The first approach doesn't require touching the API at all. We'll use the `Async Pipe`.

Pipes in Angular work the same way pipes work in Linux. They take an input and produce an output. The `Async Pipe` specifically accepts a promise or an observable, and it updates the template whenever the promise resolves or the observable emits a new value. Like all pipes, you apply it in the template.

Let's say we've got a list of products returned by an API and this service available:

```typescript
// api.service.ts

@Injectable()

  constructor(private http: HttpClient) {}

  getProducts() {
    return this.http.get('http://localhost:3000/api/products');
  }
}
```

The `getProducts()` method returns the HTTP GET call. Nothing fancy.

Now we consume this service in the component. We'll create an Observable and assign the result of `getProducts()` to it. Then we'll fire that call every 1 second, so any update at the API level gets picked up:

```typescript
// some.component.ts

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

  @Input() products$: Observable<any>;
  constructor(private api: ApiService) {}

  ngOnInit() {
    this.products$ = Observable.interval(1000)
      .startWith(0)
      .switchMap(() => this.api.getProducts());
  }
}
```

And then we wire up the `async` pipe in the template:

```html
<!-- some.component.html -->
<ul>
  <li *ngFor="let product of products$ | async">
    {{ product.prod_name }} for {{ product.price | currency:'£'}}
  </li>
</ul>
```

Push a new item to the API (or remove one), and the update shows up in the component within 1 second.

# Sockets

The second approach uses sockets. This one requires changes on both the API and the client side.

## API level modifications

At the API level, we need to enable sockets. The most widely used package for this is `socket.io`, installed via `npm i socket.io`.

Here's a server implementation using Restify and Socket.io:

```javascript
const restify = require('restify');
const server = restify.createServer();
const products = require('./products');

const io = require('socket.io')(server.server);
let sockets = new Set();

const corsMiddleware = require('restify-cors-middleware');
const port = 3000;

const cors = corsMiddleware({
  origins: ['*'],
});

server.use(restify.plugins.bodyParser());
server.pre(cors.preflight);
server.use(cors.actual);

io.on('connection', (socket) => {
  sockets.add(socket);
  socket.emit('data', { data: products });
  socket.on('clientData', (data) => console.log(data));
  socket.on('disconnect', () => sockets.delete(socket));
});

server.get('/', (request, response, next) => {
  response.end();
  next();
});

server.post('/api/products', (request, response) => {
  const product = request.body;
  products.push(product);
  for (const socket of sockets) {
    console.log(`Emitting value: ${products}`);
    socket.emit('data', { data: products });
  }
  response.json(products);
});
server.listen(port, () => console.info(`Server is up on ${port}.`));
```

> Note how Restify requires us to use `server.server` when requiring `socket.io`.

The `products` file contains an array of objects representing some data. On the first connection we send that data to the requester and stash the socket in a JavaScript `Set`:

```javascript
io.on('connection', (socket) => {
  sockets.add(socket);
  socket.emit('data', { data: products });
  socket.on('clientData', (data) => console.log(data));
  socket.on('disconnect', () => sockets.delete(socket));
});
```

When someone adds a new product (just a simple push to the `products` array), we emit the updated array to every connected client:

```javascript
server.post('/api/products', (request, response) => {
  const product = request.body;
  products.push(product);
  for (const socket of sockets) {
    console.log(`Emitting value: ${products}`);
    socket.emit('data', { data: products });
  }
  response.json(products);
});
```

> We're only covering the basics here, so the API stays deliberately simple.

## Client side modifications

On the client side, we need to connect to the socket from our Angular application. We'll use `socket.io-client` along with its typing. Install both via npm: `npm i socket.io-client @types/socket.io-client`.

Once installed, update the Angular service:

```typescript
// api.service.ts

@Injectable()

  observer: Observer<any>;

  getProducts() {
    const socket = socketIo('http://localhost:3000/');
    socket.on('data', (response) => {
      return this.observer.next(response.data);
    });
    return this.createObservable();
  }

  createObservable() {
    return new Observable((observer) => (this.observer = observer));
  }
}
```

We create an observer, connect to the socket server on port 3000, and listen for emitted data (which fires on first load and whenever someone adds a new product). That data flows into an observable, which gets passed to the component and then to the template. The template still uses the `async` pipe. The rest of the code stays the same.

Adding a new product now triggers a live update across all connected clients.

# Conclusion

Two approaches, same result. The polling method is simpler to set up but hammers the API. Sockets are more work upfront but push updates instantly. Pick whichever fits.
