I have been trying to show the elements of the array in each tab in the same way that I did in another of my pages but in the other it was a form and here it is not and that is why it gives me errors, I have changed the elements in Firebase in the Cruceros document so that instead of being descripcionQueHacer1, descripcionQueHacer2, etc., it is an array called descripcionQueHacer with all the elements but I don't know how to make it display, this is my code:
crucero.page.html
<ion-header>
<ion-toolbar color="primary">
<ion-buttons slot="start">
<ion-menu-button></ion-menu-button>
</ion-buttons>
<ion-title>{{ crucero?.name }}</ion-title>
</ion-toolbar>
</ion-header>
<ion-content>
<ion-tabs>
<ion-tab-bar slot="bottom">
<ion-tab-button tab="descripcion">
<ion-icon name="book"></ion-icon>
<ion-label>Descripción</ion-label>
</ion-tab-button>
<ion-tab-button tab="queHacer">
<ion-icon name="walk"></ion-icon>
<ion-label>Qué Hacer</ion-label>
</ion-tab-button>
<ion-tab-button tab="camarotes">
<ion-icon name="bed"></ion-icon>
<ion-label>Camarotes</ion-label>
</ion-tab-button>
<ion-tab-button tab="planos">
<ion-icon name="boat"></ion-icon>
<ion-label>Planos</ion-label>
</ion-tab-button>
</ion-tab-bar>
<ion-tab tab="descripcion">
<ion-content>
<h2 class="align-center" *ngIf="crucero?.descripcion">{{ crucero?.descripcion }}</h2>
<img [src]="crucero?.imagenDescripcion"/>
</ion-content>
</ion-tab>
<ion-tab tab="queHacer">
<ion-content>
<ion-item color="primary">
<p class="centrar" *ngIf="crucero?.tituloQueHacer1">{{ crucero?.tituloQueHacer1 }}</p>
</ion-item>
<img *ngIf="crucero?.imagenQueHacer1" [src]="crucero?.imagenQueHacer1"/>
<p class="align-center" *ngIf="crucero?.descripcionQueHacer1">{{ crucero?.descripcionQueHacer1 }}</p>
<ion-item color="primary">
<p class="centrar" *ngIf="crucero?.tituloQueHacer2">{{ crucero?.tituloQueHacer2 }}</p>
</ion-item>
<img *ngIf="crucero?.imagenQueHacer2" [src]="crucero?.imagenQueHacer2"/>
<p class="align-center" *ngIf="crucero?.descripcionQueHacer2">{{ crucero?.descripcionQueHacer2 }}</p>
<ion-item color="primary">
<p class="centrar" *ngIf="crucero?.tituloQueHacer3">{{ crucero?.tituloQueHacer3 }}</p>
</ion-item>
<img *ngIf="crucero?.imagenQueHacer3" [src]="crucero?.imagenQueHacer3"/>
<p class="align-center" *ngIf="crucero?.descripcionQueHacer3">{{ crucero?.descripcionQueHacer3 }}</p>
<ion-item color="primary">
<p class="centrar" *ngIf="crucero?.tituloQueHacer4">{{ crucero?.tituloQueHacer4 }}</p>
</ion-item>
<img *ngIf="crucero?.imagenQueHacer4" [src]="crucero?.imagenQueHacer4"/>
<p class="align-center" *ngIf="crucero?.descripcionQueHacer4">{{ crucero?.descripcionQueHacer4 }}</p>
<ion-item color="primary">
<p class="centrar" *ngIf="crucero?.tituloQueHacer5">{{ crucero?.tituloQueHacer5 }}</p>
</ion-item>
<img *ngIf="crucero?.imagenQueHacer5" [src]="crucero?.imagenQueHacer5"/>
<p class="align-center" *ngIf="crucero?.descripcionQueHacer5">{{ crucero?.descripcionQueHacer5 }}</p>
<ion-item color="primary">
<p class="centrar" *ngIf="crucero?.tituloQueHacer6">{{ crucero?.tituloQueHacer6 }}</p>
</ion-item>
<img *ngIf="crucero?.imagenQueHacer6" [src]="crucero?.imagenQueHacer6"/>
<p class="align-center" *ngIf="crucero?.descripcionQueHacer6">{{ crucero?.descripcionQueHacer6 }}</p>
</ion-content>
</ion-tab>
<ion-tab tab="camarotes">
<ion-content>
<ion-item color="primary">
<p class="centrar" *ngIf="crucero?.tituloCamarotes1">{{ crucero?.tituloCamarotes1 }}</p>
</ion-item>
<p class="align-center" *ngIf="crucero?.descripcionCamarotes1">{{ crucero?.descripcionCamarotes1 }}</p>
<img *ngIf="crucero?.imagenCamarotes1" [src]="crucero?.imagenCamarotes1"/>
<ion-item color="primary">
<p class="centrar" *ngIf="crucero?.tituloCamarotes2">{{ crucero?.tituloCamarotes2 }}</p>
</ion-item>
<p class="align-center" *ngIf="crucero?.descripcionCamarotes2">{{ crucero?.descripcionCamarotes2 }}</p>
<img *ngIf="crucero?.imagenCamarotes2" [src]="crucero?.imagenCamarotes2"/>
<ion-item color="primary">
<p class="centrar" *ngIf="crucero?.tituloCamarotes3">{{ crucero?.tituloCamarotes3 }}</p>
</ion-item>
<p class="align-center" *ngIf="crucero?.descripcionCamarotes3">{{ crucero?.descripcionCamarotes3 }}</p>
<img *ngIf="crucero?.imagenCamarotes3" [src]="crucero?.imagenCamarotes3"/>
<ion-item color="primary">
<p class="centrar" *ngIf="crucero?.tituloCamarotes4">{{ crucero?.tituloCamarotes4 }}</p>
</ion-item>
<p class="align-center" *ngIf="crucero?.descripcionCamarotes4">{{ crucero?.descripcionCamarotes4 }}</p>
<img *ngIf="crucero?.imagenCamarotes4" [src]="crucero?.imagenCamarotes4"/>
<ion-item color="primary">
<p class="centrar" *ngIf="crucero?.tituloCamarotes5">{{ crucero?.tituloCamarotes5 }}</p>
</ion-item>
<p class="align-center" *ngIf="crucero?.descripcionCamarotes5">{{ crucero?.descripcionCamarotes5 }}</p>
<img *ngIf="crucero?.imagenCamarotes5" [src]="crucero?.imagenCamarotes5"/>
<ion-item color="primary">
<p class="centrar" *ngIf="crucero?.tituloCamarotes6">{{ crucero?.tituloCamarotes6 }}</p>
</ion-item>
<p class="align-center" *ngIf="crucero?.descripcionCamarotes6">{{ crucero?.descripcionCamarotes6 }}</p>
<img *ngIf="crucero?.imagenCamarotes6" [src]="crucero?.imagenCamarotes6"/>
<ion-item color="primary">
<p class="centrar" *ngIf="crucero?.tituloCamarotes7">{{ crucero?.tituloCamarotes7 }}</p>
</ion-item>
<p class="align-center" *ngIf="crucero?.descripcionCamarotes7">{{ crucero?.descripcionCamarotes7 }}</p>
<img *ngIf="crucero?.imagenCamarotes7" [src]="crucero?.imagenCamarotes7"/>
</ion-content>
</ion-tab>
<ion-tab tab="planos">
<ion-content>
<ion-item>
<ion-label>Selecciona un plano</ion-label>
<ion-select [(ngModel)]="selectedPlano">
<ion-select-option *ngFor="let plano of planosDisponibles" [value]="plano">
{{ plano }}
</ion-select-option>
</ion-select>
</ion-item>
<img *ngIf="selectedPlano" [src]="crucero[selectedPlano]" alt="Plano seleccionado" />
</ion-content>
</ion-tab>
</ion-tabs>
</ion-content>
crucero.page.ts
import { Component, OnInit } from '@angular/core';
import { ActivatedRoute, RouterLink } from '@angular/router';
import { CrucerosService } from '../cruceros.service';
import { CommonModule } from '@angular/common';
import { IonicModule} from '@ionic/angular';
import { FormsModule } from '@angular/forms';
import { addIcons } from 'ionicons';
import { book, walk, bed, boat } from 'ionicons/icons';
@Component({
selector: 'app-crucero',
templateUrl: './crucero.page.html',
styleUrls: ['./crucero.page.scss'],
standalone: true,
imports: [CommonModule, RouterLink, IonicModule, FormsModule]
})
export class CruceroPage implements OnInit {
crucero: any = null;
idCrucero: string = '';
selectedPlano: string = '';
planosDisponibles: string[] = [];
constructor(
private route: ActivatedRoute,
private crucerosService: CrucerosService,
) {
addIcons({ book, walk, bed, boat });
}
ngOnInit() {
this.idCrucero = this.route.snapshot.paramMap.get('id')!;
this.loadCruceroDetails();
}
async loadCruceroDetails() {
const cruceroDetails = await this.crucerosService.obtenerCruceroPorId(this.idCrucero);
this.crucero = cruceroDetails;
this.planosDisponibles = Object.keys(this.crucero)
.filter(key => key.startsWith('plano'))
.map(key => {
const number = parseInt(key.replace('plano', ''), 10);
return { key, number };
})
.filter(item => this.crucero[item.key] && this.crucero[item.key] !== '')
.sort((a, b) => a.number - b.number)
.map(item => item.key);
this.selectedPlano = this.planosDisponibles.length > 0 ? this.planosDisponibles[0] : '';
}
}
cruceros.service.ts
import { inject, Injectable } from "@angular/core";
import { addDoc, collection, doc, Firestore, getDoc, getDocs, orderBy, query, setDoc } from "@angular/fire/firestore";
@Injectable({
providedIn: 'root',
})
export class CrucerosService {
private firestore = inject(Firestore);
public idCrucero: string = "";
async guardarCrucero(
idCrucero: any,
name: any,
subtitle: any,
imagenCrucero: any,
descripcion: any,
imagenDescripcion: any,
tituloQueHacer1: any,
imagenQueHacer1: any,
descripcionQueHacer1: any,
tituloQueHacer2: any,
imagenQueHacer2: any,
descripcionQueHacer2: any,
tituloQueHacer3: any,
imagenQueHacer3: any,
descripcionQueHacer3: any,
tituloQueHacer4: any,
imagenQueHacer4: any,
descripcionQueHacer4: any,
tituloQueHacer5: any,
imagenQueHacer5: any,
descripcionQueHacer5: any,
tituloQueHacer6: any,
imagenQueHacer6: any,
descripcionQueHacer6: any,
tituloCamarotes1: any,
descripcionCamarotes1: any,
imagenCamarotes1: any,
tituloCamarotes2: any,
descripcionCamarotes2: any,
imagenCamarotes2: any,
tituloCamarotes3: any,
descripcionCamarotes3: any,
imagenCamarotes3: any,
tituloCamarotes4: any,
descripcionCamarotes4: any,
imagenCamarotes4: any,
tituloCamarotes5: any,
descripcionCamarotes5: any,
imagenCamarotes5: any,
tituloCamarotes6: any,
descripcionCamarotes6: any,
imagenCamarotes6: any,
tituloCamarotes7: any,
descripcionCamarotes7: any,
imagenCamarotes7: any,
plano2: any,
plano3: any,
plano4: any,
plano5: any,
plano6: any,
plano7: any,
plano8: any,
plano9: any,
plano10: any,
plano11: any,
plano12: any,
plano13: any,
plano14: any,
plano15: any,
plano16: any,
plano17: any,
plano18: any,
plano19: any,
plano20: any,
lugar1: any,
lugar2: any,
lugar3: any,
lugar4: any,
lugar5: any,
lugar6: any,
lugar7: any,
lugar8: any,
precioLugar1: any,
precioLugar2: any,
precioLugar3: any,
precioLugar4: any,
precioLugar5: any,
precioLugar6: any,
precioLugar7: any,
precioLugar8: any,
puertos1: any,
puertos2: any,
puertos3: any,
puertos4: any,
puertos5: any,
puertos6: any,
puertos7: any,
puertos8: any
) {
const obj ={
"idCrucero" : idCrucero,
"name" : name,
"subtitle" : subtitle,
"imagenCrucero" : imagenCrucero,
"descripcion" : descripcion,
"imagenDescripcion" : imagenDescripcion,
"tituloQueHacer1" : tituloQueHacer1,
"imagenQueHacer1" : imagenQueHacer1,
"descripcionQueHacer1" : descripcionQueHacer1,
"tituloQueHacer2" : tituloQueHacer2,
"imagenQueHacer2" : imagenQueHacer2,
"descripcionQueHacer2" : descripcionQueHacer2,
"tituloQueHacer3" : tituloQueHacer3,
"imagenQueHacer3" : imagenQueHacer3,
"descripcionQueHacer3" : descripcionQueHacer3,
"tituloQueHacer4" : tituloQueHacer4,
"imagenQueHacer4" : imagenQueHacer4,
"descripcionQueHacer4" : descripcionQueHacer4,
"tituloQueHacer5" : tituloQueHacer5,
"imagenQueHacer5" : imagenQueHacer5,
"descripcionQueHacer5" : descripcionQueHacer5,
"tituloQueHacer6" : tituloQueHacer6,
"imagenQueHacer6" : imagenQueHacer6,
"descripcionQueHacer6" : descripcionQueHacer6,
"tituloCamarotes1" : tituloCamarotes1,
"descripcionCamarotes1" : descripcionCamarotes1,
"imagenCamarotes1" : imagenCamarotes1,
"tituloCamarotes2" : tituloCamarotes2,
"descripcionCamarotes2" : descripcionCamarotes2,
"imagenCamarotes2" : imagenCamarotes2,
"tituloCamarotes3" : tituloCamarotes3,
"descripcionCamarotes3" : descripcionCamarotes3,
"imagenCamarotes3" : imagenCamarotes3,
"tituloCamarotes4" : tituloCamarotes4,
"descripcionCamarotes4" : descripcionCamarotes4,
"imagenCamarotes4" : imagenCamarotes4,
"tituloCamarotes5" : tituloCamarotes5,
"descripcionCamarotes5" : descripcionCamarotes5,
"imagenCamarotes5" : imagenCamarotes5,
"tituloCamarotes6" : tituloCamarotes6,
"descripcionCamarotes6" : descripcionCamarotes6,
"imagenCamarotes6" : imagenCamarotes6,
"tituloCamarotes7" : tituloCamarotes7,
"descripcionCamarotes7" : descripcionCamarotes7,
"imagenCamarotes7" : imagenCamarotes7,
"plano2" : plano2,
"plano3" : plano3,
"plano4" : plano4,
"plano5" : plano5,
"plano6" : plano6,
"plano7" : plano7,
"plano8" : plano8,
"plano9" : plano9,
"plano10" : plano10,
"plano11" : plano11,
"plano12" : plano12,
"plano13" : plano13,
"plano14" : plano14,
"plano15" : plano15,
"plano16" : plano16,
"plano17" : plano17,
"plano18" : plano18,
"plano19" : plano19,
"plano20" : plano20,
"lugar1": lugar1,
"lugar2": lugar2,
"lugar3": lugar3,
"lugar4": lugar4,
"lugar5": lugar5,
"lugar6": lugar6,
"lugar7": lugar7,
"lugar8": lugar8,
"precioLugar1": precioLugar1,
"precioLugar2": precioLugar2,
"precioLugar3": precioLugar3,
"precioLugar4": precioLugar4,
"precioLugar5": precioLugar5,
"precioLugar6": precioLugar6,
"precioLugar7": precioLugar7,
"precioLugar8": precioLugar8,
"puertos1": puertos1,
"puertos2": puertos2,
"puertos3": puertos3,
"puertos4": puertos4,
"puertos5": puertos5,
"puertos6": puertos6,
"puertos7": puertos7,
"puertos8": puertos8
};
const Ref = collection(this.firestore, 'Cruceros');
const docRef = await addDoc(Ref, obj);
this.idCrucero = docRef.id;
console.log(idCrucero)
}
async obtenerCruceros(){
const Ref = collection(this.firestore, 'Cruceros');
const q = query(Ref, orderBy('name'));
const querySnapshot = await getDocs(q);
const cruceros = querySnapshot.docs.map(doc => ({ id:doc.id, ...doc.data()}));
return cruceros
}
async actualizarCrucero(id: string, formData: any) {
const cruceroRef = doc(this.firestore, 'Cruceros', id.toString());
await setDoc(cruceroRef, formData, { merge: true });
}
async obtenerCruceroPorId(id: string) {
const Ref = doc(this.firestore, 'Cruceros', id);
const docSnap = await getDoc(Ref);
if (docSnap.exists()) {
return docSnap.data();
} else {
console.log("No such document!");
return null;
}
}
}
Can you try below code?
<ion-header>
<ion-toolbar color="primary">
<ion-buttons slot="start">
<ion-menu-button></ion-menu-button>
</ion-buttons>
<ion-title>{{ crucero?.name }}</ion-title>
</ion-toolbar>
</ion-header>
<ion-content>
<ion-tabs>
<ion-tab-bar slot="bottom">
<ion-tab-button tab="descripcion">
<ion-icon name="book"></ion-icon>
<ion-label>Descripción</ion-label>
</ion-tab-button>
<ion-tab-button tab="queHacer">
<ion-icon name="walk"></ion-icon>
<ion-label>Qué Hacer</ion-label>
</ion-tab-button>
<ion-tab-button tab="camarotes">
<ion-icon name="bed"></ion-icon>
<ion-label>Camarotes</ion-label>
</ion-tab-button>
<ion-tab-button tab="planos">
<ion-icon name="boat"></ion-icon>
<ion-label>Planos</ion-label>
</ion-tab-button>
</ion-tab-bar>
<ion-tab tab="descripcion">
<ion-content>
<h2 class="align-center" *ngIf="crucero?.descripcion">{{ crucero?.descripcion }}</h2>
<img [src]="crucero?.imagenDescripcion"/>
</ion-content>
</ion-tab>
<ion-tab tab="queHacer">
<ion-content>
<div *ngFor="let item of crucero?.descripcionQueHacer">
<ion-item color="primary">
<p class="centrar">{{ item.titulo }}</p>
</ion-item>
<img *ngIf="item.imagen" [src]="item.imagen"/>
<p class="align-center">{{ item.descripcion }}</p>
</div>
</ion-content>
</ion-tab>
<ion-tab tab="camarotes">
<ion-content>
<ion-item color="primary">
<p class="centrar" *ngIf="crucero?.tituloCamarotes1">{{ crucero?.tituloCamarotes1 }}</p>
</ion-item>
<p class="align-center" *ngIf="crucero?.descripcionCamarotes1">{{ crucero?.descripcionCamarotes1 }}</p>
<img *ngIf="crucero?.imagenCamarotes1" [src]="crucero?.imagenCamarotes1"/>
<ion-item color="primary">
<p class="centrar" *ngIf="crucero?.tituloCamarotes2">{{ crucero?.tituloCamarotes2 }}</p>
</ion-item>
<p class="align-center" *ngIf="crucero?.descripcionCamarotes2">{{ crucero?.descripcionCamarotes2 }}</p>
<img *ngIf="crucero?.imagenCamarotes2" [src]="crucero?.imagenCamarotes2"/>
<ion-item color="primary">
<p class="centrar" *ngIf="crucero?.tituloCamarotes3">{{ crucero?.tituloCamarotes3 }}</p>
</ion-item>
<p class="align-center" *ngIf="crucero?.descripcionCamarotes3">{{ crucero?.descripcionCamarotes3 }}</p>
<img *ngIf="crucero?.imagenCamarotes3" [src]="crucero?.imagenCamarotes3"/>
<ion-item color="primary">
<p class="centrar" *ngIf="crucero?.tituloCamarotes4">{{ crucero?.tituloCamarotes4 }}</p>
</ion-item>
<p class="align-center" *ngIf="crucero?.descripcionCamarotes4">{{ crucero?.descripcionCamarotes4 }}</p>
<img *ngIf="crucero?.imagenCamarotes4" [src]="crucero?.imagenCamarotes4"/>
<ion-item color="primary">
<p class="centrar" *ngIf="crucero?.tituloCamarotes5">{{ crucero?.tituloCamarotes5 }}</p>
</ion-item>
<p class="align-center" *ngIf="crucero?.descripcionCamarotes5">{{ crucero?.descripcionCamarotes5 }}</p>
<img *ngIf="crucero?.imagenCamarotes5" [src]="crucero?.imagenCamarotes5"/>
<ion-item color="primary">
<p class="centrar" *ngIf="crucero?.tituloCamarotes6">{{ crucero?.tituloCamarotes6 }}</p>
</ion-item>
<p class="align-center" *ngIf="crucero?.descripcionCamarotes6">{{ crucero?.descripcionCamarotes6 }}</p>
<img *ngIf="crucero?.imagenCamarotes6" [src]="crucero?.imagenCamarotes6"/>
<ion-item color="primary">
<p class="centrar" *ngIf="crucero?.tituloCamarotes7">{{ crucero?.tituloCamarotes7 }}</p>
</ion-item>
<p class="align-center" *ngIf="crucero?.descripcionCamarotes7">{{ crucero?.descripcionCamarotes7 }}</p>
<img *ngIf="crucero?.imagenCamarotes7" [src]="crucero?.imagenCamarotes7"/>
</ion-content>
</ion-tab>
<ion-tab tab="planos">
<ion-content>
<ion-item>
<ion-label>Selecciona un plano</ion-label>
<ion-select [(ngModel)]="selectedPlano">
<ion-select-option *ngFor="let plano of planosDisponibles" [value]="plano">
{{ plano }}
</ion-select-option>
</ion-select>
</ion-item>
<img *ngIf="selectedPlano" [src]="crucero[selectedPlano]" alt="Plano seleccionado" />
</ion-content>
</ion-tab>
</ion-tabs>
</ion-content>
You can leave it as it is :)
import { Component, OnInit } from '@angular/core';
import { ActivatedRoute, RouterLink } from '@angular/router';
import { CrucerosService } from '../cruceros.service';
import { CommonModule } from '@angular/common';
import { IonicModule } from '@ionic/angular';
import { FormsModule } from '@angular/forms';
import { addIcons } from 'ionicons';
import { book, walk, bed, boat } from 'ionicons/icons';
@Component({
selector: 'app-crucero',
templateUrl: './crucero.page.html',
styleUrls: ['./crucero.page.scss'],
standalone: true,
imports: [CommonModule, RouterLink, IonicModule, FormsModule]
})
export class CruceroPage implements OnInit {
crucero: any = null;
idCrucero: string = '';
selectedPlano: string = '';
planosDisponibles: string[] = [];
constructor(
private route: ActivatedRoute,
private crucerosService: CrucerosService,
) {
addIcons({ book, walk, bed, boat });
}
ngOnInit() {
this.idCrucero = this.route.snapshot.paramMap.get('id')!;
this.loadCruceroDetails();
}
async loadCruceroDetails() {
const cruceroDetails = await this.crucerosService.obtenerCruceroPorId(this.idCrucero);
this.crucero = cruceroDetails;
this.planosDisponibles = Object.keys(this.crucero)
.filter(key => key.startsWith('plano'))
.map(key => {
const number = parseInt(key.replace('plano', ''), 10);
return { key, number };
})
.filter(item => this.crucero[item.key] && this.crucero[item.key] !== '')
.sort((a, b) => a.number - b.number)
.map(item => item.key);
this.selectedPlano = this.planosDisponibles.length > 0 ? this.planosDisponibles[0] : '';
}
}