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
Array of genre objectsGenre 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>
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>
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>
The ID of the genre to update
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>
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.');
}
});
}
}
}
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)
});
}
}
}
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