Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/AngheloMP10/biblioteca-virtual-frontend/llms.txt

Use this file to discover all available pages before exploring further.

Overview

The GeneroService provides methods to create, read, update, and delete book genres in the Biblioteca Virtual system. It handles all HTTP communications with the backend /generos endpoint. Location: src/app/core/services/genero.ts

Constructor

private http = inject(HttpClient);
Uses Angular’s inject() function to obtain HttpClient instance.

Properties

apiUrl
string
default:"${environment.apiUrl}/generos"
Base URL for genero endpoints, configured from environment settings.

Methods

getAll()

Retrieves all genres from the database.
getAll(): Observable<Genero[]>
Returns: Observable<Genero[]> - Array of all genres
Genero[]
array
Array of genre objects
id
number
Unique genre identifier
nombre
string
Genre name (e.g., “Ciencia Ficción”, “Romance”, “Terror”)
Example:
this.generoService.getAll().subscribe({
  next: (generos) => {
    console.log(`Found ${generos.length} genres`);
    this.genres = generos;
  },
  error: (error) => {
    console.error('Error fetching genres:', error);
  }
});
API Endpoint: GET ${apiUrl}

getById()

Retrieves a specific genre by its ID.
getById(id: number): Observable<Genero>
id
number
required
The unique identifier of the genre to retrieve
Returns: Observable<Genero> - Single genre object Example:
const generoId = 3;

this.generoService.getById(generoId).subscribe({
  next: (genero) => {
    console.log('Genre details:', genero.nombre);
    this.selectedGenre = genero;
  },
  error: (error) => {
    console.error('Genre not found:', error);
  }
});
API Endpoint: GET ${apiUrl}/{id} Use Case: Loading genre data for editing forms

create()

Creates a new genre in the database.
create(genero: Genero): Observable<Genero>
genero
Genero
required
Genre data to createRequired Properties:
  • nombre (string): Genre name
Optional Properties:
  • id (number): Should be omitted for new genres (server assigns)
Returns: Observable<Genero> - The created genre with server-assigned ID Example:
const newGenre: Genero = {
  id: 0, // Will be assigned by server
  nombre: 'Ciencia Ficción'
};

this.generoService.create(newGenre).subscribe({
  next: (createdGenero) => {
    console.log('Genre created with ID:', createdGenero.id);
    this.router.navigate(['/generos']);
  },
  error: (error) => {
    console.error('Error creating genre:', error);
  }
});
API Endpoint: POST ${apiUrl}

update()

Updates an existing genre.
update(id: number, genero: Genero): Observable<Genero>
id
number
required
The ID of the genre to update
genero
Genero
required
Updated genre dataProperties:
  • id (number): Genre ID (should match path parameter)
  • nombre (string): Updated genre name
Returns: Observable<Genero> - The updated genre object Example:
const updatedGenre: Genero = {
  id: 3,
  nombre: 'Ciencia Ficción Moderna'
};

this.generoService.update(3, updatedGenre).subscribe({
  next: (genero) => {
    console.log('Genre updated successfully:', genero.nombre);
    this.loadGenres();
  },
  error: (error) => {
    console.error('Error updating genre:', error);
  }
});
API Endpoint: PUT ${apiUrl}/{id}

delete()

Deletes a genre from the database.
delete(id: number): Observable<any>
id
number
required
The ID of the genre to delete
Returns: Observable<any> - Plain text response from server Response Type: Text (uses responseType: 'text' to accept string responses from backend) Example:
const generoId = 3;

if (confirm('¿Está seguro de eliminar este género?')) {
  this.generoService.delete(generoId).subscribe({
    next: (response) => {
      console.log('Delete response:', response);
      this.loadGenres(); // Refresh the list
    },
    error: (error) => {
      console.error('Error deleting genre:', error);
      // May occur if genre has associated books
    }
  });
}
API Endpoint: DELETE ${apiUrl}/{id} Note: Deletion may fail if the genre has associated books. Handle this error appropriately in your UI.

Complete CRUD Example

Example component using all GeneroService methods:
import { Component, OnInit, inject } from '@angular/core';
import { GeneroService } from '../core/services/genero';
import { Genero } from '../core/models/genero';
import { Router } from '@angular/router';

@Component({
  selector: 'app-genero-list',
  templateUrl: './genero-list.html'
})
export class GeneroListComponent implements OnInit {
  generoService = inject(GeneroService);
  router = inject(Router);
  generos: Genero[] = [];
  loading = false;

  ngOnInit() {
    this.loadGeneros();
  }

  loadGeneros() {
    this.loading = true;
    this.generoService.getAll().subscribe({
      next: (data) => {
        this.generos = data;
        this.loading = false;
      },
      error: (err) => {
        console.error('Error loading genres:', err);
        this.loading = false;
      }
    });
  }

  editGenero(id: number) {
    this.router.navigate(['/generos/editar', id]);
  }

  deleteGenero(id: number, nombre: string) {
    if (confirm(`¿Eliminar género "${nombre}"?`)) {
      this.generoService.delete(id).subscribe({
        next: () => {
          this.loadGeneros();
        },
        error: (err) => {
          alert('No se puede eliminar el género. Puede tener libros asociados.');
        }
      });
    }
  }
}

Form Example

Example form component for creating/editing genres:
import { Component, OnInit, inject } from '@angular/core';
import { ActivatedRoute, Router } from '@angular/router';
import { GeneroService } from '../core/services/genero';
import { Genero } from '../core/models/genero';

@Component({
  selector: 'app-genero-form',
  templateUrl: './genero-form.html'
})
export class GeneroFormComponent implements OnInit {
  generoService = inject(GeneroService);
  route = inject(ActivatedRoute);
  router = inject(Router);

  genero: Genero = { id: 0, nombre: '' };
  isEditMode = false;

  ngOnInit() {
    const id = this.route.snapshot.paramMap.get('id');
    if (id) {
      this.isEditMode = true;
      this.loadGenero(Number(id));
    }
  }

  loadGenero(id: number) {
    this.generoService.getById(id).subscribe({
      next: (data) => {
        this.genero = data;
      }
    });
  }

  save() {
    if (this.isEditMode) {
      this.generoService.update(this.genero.id, this.genero).subscribe({
        next: () => this.router.navigate(['/generos']),
        error: (err) => console.error('Error updating:', err)
      });
    } else {
      this.generoService.create(this.genero).subscribe({
        next: () => this.router.navigate(['/generos']),
        error: (err) => console.error('Error creating:', err)
      });
    }
  }
}

Usage in Forms

GeneroService is commonly used to populate dropdown selectors when creating/editing books:
import { Component, OnInit, inject } from '@angular/core';
import { GeneroService } from '../core/services/genero';
import { LibroService } from '../core/services/libro';
import { Genero } from '../core/models/genero';

@Component({
  selector: 'app-libro-form',
  templateUrl: './libro-form.html'
})
export class LibroFormComponent implements OnInit {
  generoService = inject(GeneroService);
  libroService = inject(LibroService);
  
  availableGenres: Genero[] = [];
  selectedGenre?: Genero;

  ngOnInit() {
    // Load all genres for the dropdown
    this.generoService.getAll().subscribe({
      next: (generos) => {
        this.availableGenres = generos;
      }
    });
  }

  saveBook() {
    const bookData = {
      titulo: 'Book Title',
      genero: this.selectedGenre,
      // ... other fields
    };
    
    this.libroService.create(bookData).subscribe({
      next: (libro) => console.log('Book created with genre:', libro.genero.nombre)
    });
  }
}

Data Model

Genero Interface

export interface Genero {
  id: number;
  nombre: string;
}

Error Handling

Common error scenarios and how to handle them:
this.generoService.create(newGenre).subscribe({
  next: (response) => { /* success */ },
  error: (error) => {
    if (error.status === 400) {
      console.error('Invalid genre data');
    } else if (error.status === 409) {
      console.error('Genre name already exists');
    } else if (error.status === 403) {
      console.error('Access forbidden: admin privileges required');
    } else {
      console.error('Unexpected error:', error);
    }
  }
});

See Also

Build docs developers (and LLMs) love