Angular 5:组件间API数据传递及DataService使用求助
No worries, let's get this sorted out! Using a shared DataService is perfect for passing data between components and encapsulating your API logic cleanly. Here's a complete, working example tailored to your needs:
1. Create the Shared DataService
First, generate a service (run ng generate service data via Angular CLI if you haven't already) and add this code. It’ll handle storing the correo value and all your API calls:
import { Injectable } from '@angular/core'; import { HttpClient } from '@angular/common/http'; import { BehaviorSubject, Observable } from 'rxjs'; import { tap } from 'rxjs/operators'; @Injectable({ providedIn: 'root' // Makes this service available across your entire app }) export class DataService { // BehaviorSubject holds the current value and emits it to new subscribers immediately private correoSubject = new BehaviorSubject<string>(''); public correo$ = this.correoSubject.asObservable(); // Expose as observable to components constructor(private http: HttpClient) { } // API call to validate the submitted form data validateForm(formData: any): Observable<any> { return this.http.post('https://your-validation-api-url.com/validate', formData); } // Update the stored correo value in the service setCorreo(correo: string): void { this.correoSubject.next(correo); } // API call to send correo and fetch the final data sendCorreoAndGetData(correo: string): Observable<any> { return this.http.post('https://your-target-api-url.com/submit', { correo }); } }
2. Form Component: Handle Input, Validation, and Pass Correo
In your form component (where users enter their data), inject the DataService and Router to navigate to the target component after successful validation:
import { Component } from '@angular/core'; import { FormBuilder, FormGroup, Validators } from '@angular/forms'; import { DataService } from './data.service'; import { Router } from '@angular/router'; import { catchError } from 'rxjs/operators'; import { of } from 'rxjs'; @Component({ selector: 'app-form', template: ` <form [formGroup]="myForm" (ngSubmit)="onSubmit()"> <input type="email" formControlName="correo" placeholder="Correo electrónico" required> <!-- Add other form fields here --> <button type="submit" [disabled]="!myForm.valid">Enviar</button> </form> ` }) export class FormComponent { myForm: FormGroup; constructor( private fb: FormBuilder, private dataService: DataService, private router: Router ) { // Initialize form with validation rules this.myForm = this.fb.group({ correo: ['', [Validators.required, Validators.email]], // Add other form controls with validators as needed }); } onSubmit(): void { if (this.myForm.valid) { const formData = this.myForm.value; // First, validate the form data via your API this.dataService.validateForm(formData) .pipe( catchError(error => { console.error('Validación fallida:', error); // Add user-friendly error handling here (e.g., show a toast) return of(null); }) ) .subscribe(validationResponse => { if (validationResponse?.success) { // If validation passes, store correo in the DataService this.dataService.setCorreo(formData.correo); // Navigate to the target component this.router.navigate(['/target-component']); } }); } } }
3. Target Component: Retrieve Correo and Send to API
In your target component, subscribe to the correo$ observable from the service, store the value, and make the second API call:
import { Component, OnInit, OnDestroy } from '@angular/core'; import { DataService } from './data.service'; import { Subscription } from 'rxjs'; @Component({ selector: 'app-target', template: ` <div *ngIf="correo"> <p>Procesando correo: {{ correo }}</p> <div *ngIf="apiResponse"> <h4>Respuesta del API:</h4> <pre>{{ apiResponse | json }}</pre> </div> </div> ` }) export class TargetComponent implements OnInit, OnDestroy { correo: string | null = null; apiResponse: any; private correoSubscription: Subscription | undefined; constructor(private dataService: DataService) { } ngOnInit(): void { // Subscribe to changes in the stored correo value this.correoSubscription = this.dataService.correo$.subscribe(correo => { if (correo) { this.correo = correo; // Call the second API with the retrieved correo this.sendCorreoToApi(correo); } }); } sendCorreoToApi(correo: string): void { this.dataService.sendCorreoAndGetData(correo) .subscribe(response => { this.apiResponse = response; // Handle the API response (display data, update UI, etc.) }, error => { console.error('Llamada al API fallida:', error); // Add error handling here }); } ngOnDestroy(): void { // Clean up the subscription to prevent memory leaks this.correoSubscription?.unsubscribe(); } }
Key Notes to Remember
- Don’t forget to import
HttpClientModulein your rootAppModule(required for all HTTP calls):import { HttpClientModule } from '@angular/common/http'; @NgModule({ imports: [HttpClientModule], // ... other imports and declarations }) export class AppModule { } - For simpler subscription management, you can use the
asyncpipe in the template (e.g.,{{ dataService.correo$ | async }}) instead of manual subscriptions. - Add user-friendly error messages and loading states to improve the user experience.
内容的提问来源于stack exchange,提问作者Netox

