You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Angular父子组件:点击文章列表触发详情组件加载的技术实现咨询

Got it, let's walk through implementing these two Angular components exactly as you described. I'll provide clean, tested code snippets with explanations for each part:

文章列表组件(Article List Component)

This component handles displaying articles in a table, managing the selected article ID, and passing it to the detail component.

Component Class (article-list.component.ts)

import { Component } from '@angular/core';

// 示例文章接口
interface Article {
  id: number;
  title: string;
  author: string;
  publishDate: string;
}

@Component({
  selector: 'app-article-list',
  templateUrl: './article-list.component.html',
  styleUrls: ['./article-list.component.css']
})
export class ArticleListComponent {
  // 模拟文章数据(实际项目替换为API请求结果)
  articles: Article[] = [
    { id: 1, title: 'Angular Reactive Forms 101', author: 'Jane Doe', publishDate: '2024-01-15' },
    { id: 2, title: 'Mastering Angular Inputs & Outputs', author: 'John Smith', publishDate: '2024-02-20' },
    { id: 3, title: 'Optimizing Angular Component Performance', author: 'Sam Wilson', publishDate: '2024-03-10' }
  ];

  // 存储选中的文章ID,用于传递给详情组件
  selectedArticleId: number | null = null;

  // 处理行点击事件,设置选中的文章ID
  selectArticle(articleId: number): void {
    this.selectedArticleId = articleId;
  }
}

Template (article-list.component.html)

We'll use a table for display, with each row clickable to trigger selection. We also embed the detail component and pass the selected ID via @Input:

<div class="article-list-container">
  <h2>文章列表</h2>
  <table>
    <thead>
      <tr>
        <th>标题</th>
        <th>作者</th>
        <th>发布日期</th>
      </tr>
    </thead>
    <tbody>
      <!-- 点击每行时触发selectArticle方法,标记选中状态 -->
      <tr 
        *ngFor="let article of articles" 
        (click)="selectArticle(article.id)"
        [class.selected]="article.id === selectedArticleId"
      >
        <td>{{ article.title }}</td>
        <td>{{ article.author }}</td>
        <td>{{ article.publishDate }}</td>
      </tr>
    </tbody>
  </table>

  <!-- 引入文章详情组件,传递选中的文章ID -->
  <app-article-detail [articleId]="selectedArticleId"></app-article-detail>
</div>

Optional CSS (article-list.component.css)

Add styling to highlight the selected row for better UX:

table {
  width: 100%;
  border-collapse: collapse;
  margin-bottom: 20px;
}

th, td {
  border: 1px solid #ddd;
  padding: 8px;
  text-align: left;
}

tr:hover {
  background-color: #f5f5f5;
}

tr.selected {
  background-color: #e3f2fd;
}

文章详情组件(Article Detail Component)

This component listens for the incoming article ID, fetches detailed data, and populates a reactive form with the article properties.

Component Class (article-detail.component.ts)

import { Component, Input, OnChanges, SimpleChanges } from '@angular/core';
import { FormBuilder, FormGroup } from '@angular/forms';

// 文章详情接口(包含更多属性)
interface ArticleDetail {
  id: number;
  title: string;
  author: string;
  publishDate: string;
  content: string;
  category: string;
  readCount: number;
}

@Component({
  selector: 'app-article-detail',
  templateUrl: './article-detail.component.html',
  styleUrls: ['./article-detail.component.css']
})
export class ArticleDetailComponent implements OnChanges {
  // 接收来自列表组件的文章ID
  @Input() articleId: number | null = null;

  // 响应式表单组
  articleForm: FormGroup;

  // 模拟文章详情数据(实际项目替换为HTTP请求)
  private articleDetails: ArticleDetail[] = [
    { 
      id: 1, 
      title: 'Angular Reactive Forms 101', 
      author: 'Jane Doe', 
      publishDate: '2024-01-15',
      content: 'Reactive Forms provide a model-driven approach to handling form inputs. They offer better control over form validation, value changes, and state management compared to template-driven forms.',
      category: 'Angular',
      readCount: 1200
    },
    { 
      id: 2, 
      title: 'Mastering Angular Inputs & Outputs', 
      author: 'John Smith', 
      publishDate: '2024-02-20',
      content: 'Inputs and Outputs are core to component communication in Angular. Inputs let you pass data from parent to child, while Outputs emit events from child to parent.',
      category: 'Angular',
      readCount: 850
    },
    { 
      id: 3, 
      title: 'Optimizing Angular Component Performance', 
      author: 'Sam Wilson', 
      publishDate: '2024-03-10',
      content: 'Performance optimization is key for large Angular applications. Techniques like OnPush change detection, lazy loading, and memoization can drastically improve app speed.',
      category: 'Angular',
      readCount: 1500
    }
  ];

  constructor(private fb: FormBuilder) {
    // 初始化表单组,定义所有需要的控件
    this.articleForm = this.fb.group({
      title: [''],
      author: [''],
      publishDate: [''],
      content: [''],
      category: [''],
      readCount: ['']
    });
  }

  // 监听articleId的变化,触发详情加载
  ngOnChanges(changes: SimpleChanges): void {
    // 检查articleId是否有变化,且不为null
    if (changes['articleId'] && this.articleId !== null) {
      this.loadArticleDetail(this.articleId);
    }
  }

  // 根据ID加载文章详情,并更新表单
  private loadArticleDetail(articleId: number): void {
    // 模拟从数据源获取详情(实际项目用HttpClient请求API)
    const detail = this.articleDetails.find(art => art.id === articleId);
    
    if (detail) {
      // 将详情数据填充到表单中
      this.articleForm.patchValue(detail);
    } else {
      // 如果没有找到对应ID的文章,重置表单
      this.articleForm.reset();
    }
  }
}

Template (article-detail.component.html)

Bind the reactive form to the template, displaying each field (marked as readonly here since it's a detail view):

<div class="article-detail-container" *ngIf="articleId">
  <h2>文章详情</h2>
  <form [formGroup]="articleForm">
    <div class="form-group">
      <label>标题:</label>
      <input type="text" formControlName="title" readonly>
    </div>

    <div class="form-group">
      <label>作者:</label>
      <input type="text" formControlName="author" readonly>
    </div>

    <div class="form-group">
      <label>发布日期:</label>
      <input type="text" formControlName="publishDate" readonly>
    </div>

    <div class="form-group">
      <label>分类:</label>
      <input type="text" formControlName="category" readonly>
    </div>

    <div class="form-group">
      <label>阅读量:</label>
      <input type="number" formControlName="readCount" readonly>
    </div>

    <div class="form-group">
      <label>内容:</label>
      <textarea formControlName="content" rows="8" readonly></textarea>
    </div>
  </form>
</div>

<div *ngIf="!articleId" class="empty-state">
  请从列表中选择一篇文章查看详情
</div>

Optional CSS (article-detail.component.css)

Add basic styling for the form:

.article-detail-container {
  padding: 20px;
  border: 1px solid #ddd;
  border-radius: 8px;
}

.form-group {
  margin-bottom: 15px;
}

label {
  display: block;
  margin-bottom: 5px;
  font-weight: bold;
}

input, textarea {
  width: 100%;
  padding: 8px;
  border: 1px solid #ddd;
  border-radius: 4px;
}

.empty-state {
  padding: 20px;
  text-align: center;
  color: #666;
  border: 1px dashed #ddd;
  border-radius: 8px;
}

Key Notes:

  • Component Communication: We use @Input() to pass the selected article ID from the list to the detail component—this is a standard parent-child communication pattern in Angular.
  • Reactive Forms: The detail component uses Angular's Reactive Forms module to manage form state, which is ideal for handling complex data binding and future validation if needed.
  • Change Detection: ngOnChanges ensures we reload the article detail whenever a new article is selected, keeping the view in sync with the selected ID.
  • Mock Data: In a real application, replace the mock article arrays with HTTP requests using Angular's HttpClient to fetch data from your backend API.

内容的提问来源于stack exchange,提问作者Brijesh

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 03:34:57