为什么切换到交易子页面后看不到数据?

前端开发 2026-07-09

假设我有两页:第一页用于创建数据(交易),第二页用于在表格中显示交易。我也为这些子页设置导航('/create-transaction' 和 '/transactions'))。

我创建了一笔交易,它会写入数据库(Postgres),于是我跳转到 /users子页查看结果。点击链接后,页面什么都没有显示……再按F5刷新页面或再次点击导航中的链接,数据才会显示。我想知道为什么在跳转到子页后它们没有立即显示。

transactions-list.tscreate-transaction.ts

import { Component, inject, OnInit, signal } from '@angular/core';
import { NgClass } from '@angular/common';
import { TransactionsService } from '../../../core/services/transactions';
import { Transaction } from '../../../core/models/transaction.model';
import { CommonModule } from '@angular/common';

@Component({
  selector: 'app-transaction-list',
  standalone: true,
  imports: [NgClass, CommonModule],
  templateUrl: './transaction-list.html',
  styleUrl: './transaction-list.scss',
})
export class TransactionList implements OnInit {
  loading = signal(false);

  private readonly transactionsService = inject(TransactionsService);
  transactions: Transaction[] = [];

  ngOnInit(): void {
    this.loadTransactions();
  }

  loadTransactions(): void {
    this.loading.set(true);
    this.transactions = [];

    this.transactionsService.getTransactions().subscribe({
      next: (data) => {
        console.log('Transactions loaded:', data);
        this.transactions = [...data];
        this.loading.set(false);
      },
      error: (error) => {
        console.error('Error loading transactions:', error);
        this.loading.set(false);
      }
    });
  }
}

import { Component, EventEmitter, inject, Output, signal } from '@angular/core';
import { FormBuilder, ReactiveFormsModule, Validators } from '@angular/forms';
import { CommonModule } from '@angular/common';
import { CategoriesService } from '../../../core/services/categories';
import { Category } from '../../../core/models/category.model';
import { TransactionsService } from '../../../core/services/transactions';
import { Transaction } from '../../../core/models/transaction.model';

@Component({
  selector: 'app-create-transaction-form',
  standalone: true,
  imports: [CommonModule, ReactiveFormsModule],
  templateUrl: './create-transaction-form.html',
  styleUrl: './create-transaction-form.scss',
})
export class CreateTransactionForm {
  // private fb = inject(FormBuilder);
  private readonly fb = inject(FormBuilder);
  private readonly transactionsService = inject(TransactionsService);

  @Output() transactionCreated = new EventEmitter<Transaction>();

  private readonly categoriesService = inject(CategoriesService);
  categories: Category[] = [];

  loading = signal(false);

  form = this.fb.nonNullable.group({
    transactionName: ['', [Validators.required, Validators.minLength(2)]],
    transactionType: ['income'],
    transactionAmount: ['', [Validators.required, Validators.min(0.01)]],
    transactionCategory: ['', [Validators.required]],
    transactionDate: ['', [Validators.required]],
    transactionDescription: [''/*, [Validators.required, Validators.maxLength(200)]*/],
  });

  onSubmit(): void {
    if (this.form.invalid) {
      this.form.markAllAsTouched();
      return;
    }

    this.loading.set(true);

    const formValue = this.form.getRawValue();

    const payload = {
      name: formValue.transactionName,
      type: formValue.transactionType,
      amount: Number(formValue.transactionAmount),
      category: formValue.transactionCategory,
      completedAt: formValue.transactionDate,
      description: formValue.transactionDescription
    };

    this.transactionsService.createTransaction(payload).subscribe({
      next: (transaction) => {
        this.transactionCreated.emit(transaction);
        this.form.reset({
          transactionName: '',
          transactionType: 'income',
          transactionAmount: '',
          transactionCategory: '',
          transactionDate: '',
          transactionDescription: '',
        });
        this.loading.set(false);
      },
      error: (error) => {
        console.error('Error creating transaction: ', error);
        this.loading.set(false);
      }
    });
  }

  ngOnInit(): void {
    this.loadCategories();
  }

  loadCategories(): void {
    this.loading.set(true);

    this.categoriesService.getCategories().subscribe({
      next: (data) => {
        this.categories = data;
        this.loading.set(false);
      },
      error: (error) => {
        console.error('Error loading categories:', error);
        this.loading.set(false);
      },
    });
  }
}

transaction.ts (TransactionService)

import { HttpClient } from '@angular/common/http';
import { inject, Injectable } from '@angular/core';
import { Observable } from 'rxjs';
import { Transaction } from '../models/transaction.model';

@Injectable({
  providedIn: 'root',
})
export class TransactionsService {
  private readonly apiUrl = 'http://localhost:3000/transactions';
  private readonly http = inject(HttpClient);

  getTransactions(): Observable<Transaction[]> {
    return this.http.get<Transaction[]>(this.apiUrl);
  }

  createTransaction(
    data: {
      name: string,
      type: string,
      amount: number,
      category: string,
      completedAt: string,
      description: string,
    }
  ): Observable<Transaction> {
    return this.http.post<Transaction>(this.apiUrl, data);
  }
}

transaction-list.html

<table class="transactions-table">
  <thead>
    <tr>
      <th>Názov</th>
      <th>Typ</th>
      <th>Suma</th>
      <th>Kategória</th>
      <th>Zrealizovaná dňa</th>
      <th>Popis</th>
    </tr>
  </thead>
  <tbody>
    @for (t of transactions; track t.amount) {
      <tr>
        <td>{{ t.name }}</td>
        <td>
          <span [ngClass]="t.type">
            {{ t.type === 'income' ? 'Príjem' : 'Výdavok' }}
          </span>
        </td>
        <td>{{ t.amount }} €</td>
        <td>{{ t.category }}</td>
        <td>{{ t.completedAt | date: 'dd. MM. yyyy' }}</td>
        <td>{{ t.description }}</td>
      </tr>
    }
  </tbody>
</table>

解决方案

我修好了。我把状态放在组件中,而不是放在服务里

// transaction.ts (service)
import { HttpClient } from '@angular/common/http';
import { inject, Injectable, signal } from '@angular/core';
import { Observable, tap } from 'rxjs';
import { Transaction } from '../models/transaction.model';

@Injectable({
  providedIn: 'root',
})
export class TransactionsService {
  private readonly apiUrl = 'http://localhost:3000/transactions';
  private readonly http = inject(HttpClient);

  private readonly _transactions = signal<Transaction[]>([]);
  readonly transactions = this._transactions.asReadonly();
  private readonly _loading = signal(false);
  readonly loading = this._loading.asReadonly();

  getTransactions() {
    this._loading.set(true);

    return this.http.get<Transaction[]>(this.apiUrl).pipe(
      tap({
        next: (data) => {
          this._transactions.set(data);
          this._loading.set(false);
        },
        error: () => this._loading.set(false)
      })
    );
  }

  createTransaction(transaction: Partial<Transaction>) {
    return this.http.post<Transaction>(this.apiUrl, transaction).pipe(
      tap(newTransaction => {
        this._transactions.update(prev => [...prev, newTransaction]);
      })
    );
  }
}
站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。

相关文章