Home > Back-end >  Angular, how to display more than one random quote on one page?
Angular, how to display more than one random quote on one page?

Time:11-05

I am a beginner in Angular (12) and I am struggling with this issue. I want to display more than one random quote on a page. I've managed to display multiple, but they are all the same underneath eachother. I have no errors in the code. I have tried some forEach but couldn't do it. Here is the code:

app.component.html

<div class="main-content">
  <div class="joke-wrapper" *ngFor="let joke of jokes">
    <div class="joke">
      <p>{{ joke.value }}</p>
    </div>
  </div>
  <div class="joke-wrapper" *ngFor="let joke of jokes">
    <div class="joke">
      <p>{{ joke.value }}</p>
    </div>
  </div>
</div>

jokes.service.ts:

import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';

@Injectable({
  providedIn: 'root',
})
export class JokesService {
  private apiUrl = 'https://api.chucknorris.io/jokes/';
  constructor(private http: HttpClient) {}

  getRandomJoke() {
    return this.http.get(this.apiUrl   'random');
  }
}

app.component.ts:

import { Component, OnInit } from '@angular/core';
import { JokesService } from './jokes.service';

@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css'],
})
export class AppComponent implements OnInit {
jokes: any[] = [];

constructor(private jokesService: JokesService) {}

ngOnInit() {
 this.jokesService.getRandomJoke().subscribe((joke) => {
   this.jokes.push(joke);
 });
}
}

CodePudding user response:

The problem is that your array only contains one joke.

This probably works.

import { Component, OnInit } from '@angular/core';
import { JokesService } from './jokes.service';

@Component({
    selector: 'app-root',
    templateUrl: './app.component.html',
    styleUrls: ['./app.component.css'],
})
export class AppComponent implements OnInit {
    jokes: any[] = [];
    
    constructor(private jokesService: JokesService) {}
    
    ngOnInit() {
        // Multiple times
        this.addJoke();
        this.addJoke();
    }

    addJoke() {
        this.jokesService.getRandomJoke().subscribe((joke) => {
            this.jokes.push(joke);
        });
    }
}

Although I would prefer this solution:

Making use of the async pipe can get some performance gains and it is generaly cleaner code.

component ts:

import { Component, OnInit } from '@angular/core';
import { JokesService } from './jokes.service';

@Component({
    selector: 'app-root',
    templateUrl: './app.component.html',
    styleUrls: ['./app.component.css'],
})
export class AppComponent implements OnInit {
    jokes$!: Observable<any[]>;
    
    constructor(private jokesService: JokesService) {}
    
    ngOnInit() {
        this.jokes$ = this.jokesService.getRandomJokes(10);
    }
}

Service ts:

@Injectable({
    providedIn: 'root',
})
export class JokesService {
    private apiUrl = 'https://api.chucknorris.io/jokes/';
    constructor(private http: HttpClient) {}

    getRandomJoke() {
        return this.http.get(this.apiUrl   'random');
    }

    getRandomJokes(amount: number) {
        const jokes = [];

        for (let i = 0; i < amount; i  ) {
            jokes.push(this.getRandomJoke())
        }

        return forkJoin(jokes);
    }
}

component html:

<div class="main-content">
    <div class="joke-wrapper" *ngFor="let joke of jokes$ | async">
        <div class="joke">
            <p>{{ joke.value }}</p>
        </div>
    </div>
</div>
  • Related