Token导航 LogoToken导航

Agent Skill · 研究检索

angular-20-control-flow(Angular 20 control flow 搜索)

angular-20-control-flow 用于查找、检索和筛选相关信息,适合在 Codex、Claude、Cursor、Gemini CLI 中需要根据关键词、任务场景或来源线索快速定位候选结果时使用。可结合来源仓库、安装命令和原始 README 继续核验具体用法。安装前建议确认权限范围、维护状态,以及是否会触发联网、命令执行或文件读写。

angular-20-control-flow 是研究检索类 Agent Skill,可用宿主为 Codex、Claude、Cursor、Gemini CLI,通过GitHub 仓库获取,权限为操作浏览器;许可证为 MIT,暂无第三方扫描结果,按安装量在研究检索类的 73,675 个 Skill 里排第 49,632。

总安装 643周安装 26GitHub Stars 公开资料未说明下载 202核验 2026-05-01

安装说明

本站只整理中文说明,不托管安装包,也不代用户安装。
GitHub
许可证
MIT

安装方式

通过对话安装

复制提示词发给支持本地命令或 Skills 的 AI 助手,先确认命令和权限,再让它执行。

请帮我安装这个 Agent Skill:angular-20-control-flow(Angular 20 control flow 搜索)
来源仓库:https://github.com/7spade/black-tortoise
仓库路径:skills/angular-20-control-flow
安装命令:
npx skills add 7spade/black-tortoise --skill "angular-20-control-flow"
安装前请先检查当前环境是否支持对应 CLI,并向我确认将要执行的命令、安装目录、联网范围和文件读写权限;确认后再执行。

命令行安装

复制命令到本机终端执行。该命令会通过 npx skills 从第三方来源获取 Skill;本站只展示命令,不托管安装包,也不自动执行。

AgentSkills.tonpx skills
npx skills add 7spade/black-tortoise --skill "angular-20-control-flow"

这个 Skill 是做什么的

研究检索类 Skill 主要解决「找资料、核对事实、把来源整理清楚」的问题,通常会让助手先检索再总结。

angular-20-control-flow 用于查找、检索和筛选相关信息,适合在 Codex、Claude、Cursor、Gemini CLI 中需要根据关键词快速定位候选结果时使用。它支持基于任务场景或来源线索进行信息聚合与筛选,适用于研究类工作流。

通过 npx skills add 7spade/black-tortoise --skill "angular-20-control-flow" 命令安装。安装前建议确认权限范围、维护状态,以及是否会触发联网或文件读写操作。

适用宿主包括 Codex、Claude、Cursor、Gemini CLI,接入前应确认版本、权限和运行环境要求。

来源仓库内路径:skills/angular-20-control-flow

上手步骤

4 步
  1. 1

    确认自己的宿主工具

    公开资料标注支持 Codex、Claude、Cursor、Gemini CLI;先确认自己用的是其中之一,再按对应工具的 Skills 目录放置。

  2. 2

    拿到安装命令

    可以直接复制的命令是 npx skills add 7spade/black-tortoise --skill "angular-20-control-flow";命令里的占位符换成自己的路径或密钥再执行。

  3. 3

    安装后重启宿主

    命令执行完要完全退出宿主工具再打开,让新装的 Skill 被重新扫描到,否则列表里可能看不到。

  4. 4

    按最小权限试用

    它需要操作浏览器,先在测试目录或测试账号里跑,确认没问题再放到正式项目。

常见问题

6 条

angular-20-control-flow 怎么安装?

在终端执行 npx skills add 7spade/black-tortoise --skill "angular-20-control-flow"。装完完全退出宿主工具再打开,让它重新扫描本地 Skill。

angular-20-control-flow 支持哪些 AI 工具?

公开资料标注支持 Codex、Claude、Cursor、Gemini CLI。其他工具只要能读取本地 Skill 目录,一般也能手动放进去,但要自己确认触发方式是否一致。

angular-20-control-flow 需要什么权限?

权限级别是操作浏览器。该 Skill 可能涉及浏览器控制能力,使用时可能读取或操作网页内容,需要在受控环境中确认权限边界。

angular-20-control-flow 是免费的吗?

来源标注的许可证是 MIT。本站不代收任何费用,也不托管安装包;能否商用、要不要署名,以许可证原文为准。

angular-20-control-flow 用的人多吗?

公开数据是累计安装 643 次,近一周安装 26 次,下载 202 次。这些数字来自第三方目录统计,只能当作热度参考,不代表质量或安全性。

angular-20-control-flow 安全吗?

没有查到第三方扫描结果,安全性无法从公开资料判断,安装前请自行审查源码、依赖和命令行为。

值得选的地方和要先想清楚的地方

值得选的地方

  • 同时适配 4 种工具,换客户端不用重新找替代品。
  • 许可证明确为 MIT,商用和分发边界好判断。

先想清楚的地方

  • 没有第三方扫描结果,安全性只能靠自己读源码判断。
  • 第三方目录整理,版本更新和行为细节以来源仓库为准。

适不适合你

更适合

  • 已经在用 Codex,想直接扩展它能力的人。
  • 需要处理研究检索类任务、又不想每次都手写提示词的人。

不太适合

  • 要求有安全扫描结论才肯安装的团队。
  • 需要厂商级技术支持和 SLA 的生产系统。

研究检索类 Skill 对比

6 个同类
Skill总安装GitHub 星权限许可证扫描
find-skills

寻找技能 · Codex、Claude

31,199,81316,486操作浏览器MIT有提醒
self-improving-agent

自我改进 Agent · OpenClaw

16,464,0023,396接触敏感数据MIT-0通过
soultrace

灵魂追踪 · Codex、Claude

7,588,94412需要联网未明确有提醒
self-improving

自我完善 · OpenClaw

6,829,2841,046需要联网MIT-0通过
microsoft-foundry

微软代工厂 · Codex、Claude

6,614,144764调用外部服务未明确有提醒
angular-20-control-flow

Angular 20 control flow 搜索 · 本页

643—操作浏览器MIT未收录

按安装量取同分类前几名;数字来自第三方目录统计,只作热度参考,不代表质量结论。

SKILL.md 原文

name
angular-20-control-flow
description
Angular 20 built-in control flow syntax (@if, @for, @switch, @defer) for modern template programming. Use when writing templates with conditional rendering, loops, switch statements, or lazy loading components. Replaces *ngIf, *ngFor, *ngSwitch with new block syntax for better performance and type safety.
license
MIT

Angular 20 Control Flow Skill

Rules

Control Flow Syntax

  • Use @if / @else / @else if for conditional rendering
  • Use @for with mandatory track expression for list iteration
  • Use @switch / @case / @default for multi-branch conditionals
  • Use @defer for lazy loading and code splitting
  • MUST NOT use structural directives: *ngIf, *ngFor, *ngSwitch

@for Track Expression

  • Every @for loop MUST include a track expression
  • Track by unique ID: track item.id
  • Track by index for static lists: track $index
  • MUST NOT track by object reference

@defer Loading States

  • Use appropriate trigger: on viewport, on interaction, on idle, on immediate, on timer(Xs), on hover
  • Use @loading (minimum Xms) to prevent UI flashing
  • Use @placeholder (minimum Xms) for minimum display time

Signal Integration

  • Control flow conditions MUST use signal invocation: @if (signal())
  • MUST NOT use plain properties without signal invocation

Context Variables

  • Available in @for: $index, $first, $last, $even, $odd, $count

Context

Purpose

This skill provides comprehensive guidance on Angular 20's built-in control flow syntax, which introduces new template syntax (@if, @for, @switch, @defer) that replaces structural directives with better performance, type safety, and developer experience.

What is Angular Control Flow?

Angular 20 introduces new built-in control flow syntax:

  • @if / @else: Conditional rendering (replaces *ngIf)
  • @for: List iteration with tracking (replaces *ngFor)
  • @switch / @case: Multi-branch conditionals (replaces *ngSwitch)
  • @defer: Lazy loading and code splitting (new feature)
  • @empty: Fallback for empty collections
  • @placeholder / @loading / @error: Defer states

When to Use This Skill

Use Angular 20 Control Flow when:

  • Writing templates with conditional rendering
  • Iterating over lists or arrays
  • Implementing switch/case logic in templates
  • Lazy loading components or content blocks
  • Handling loading states and error boundaries
  • Optimizing bundle size with deferred loading
  • Migrating from *ngIf, *ngFor, *ngSwitch to modern syntax

Core Control Flow Blocks

1. @if - Conditional Rendering

Basic Usage:

@Component({
  template: `
    @if (isLoggedIn()) {
      <div>Welcome back, {{ username() }}!</div>
    }
  `
})
export class WelcomeComponent {
  isLoggedIn = signal(false);
  username = signal('User');
}

@if with @else:

@Component({
  template: `
    @if (user()) {
      <app-dashboard [user]="user()" />
    } @else {
      <app-login />
    }
  `
})
export class AppComponent {
  user = signal<User | null>(null);
}

@if with @else if:

@Component({
  template: `
    @if (status() === 'loading') {
      <app-spinner />
    } @else if (status() === 'error') {
      <app-error [message]="errorMessage()" />
    } @else if (status() === 'success') {
      <app-content [data]="data()" />
    } @else {
      <app-empty-state />
    }
  `
})
export class DataComponent {
  status = signal<'loading' | 'error' | 'success' | 'idle'>('idle');
  errorMessage = signal('');
  data = signal<any[]>([]);
}

Type Narrowing:

@Component({
  template: `
    @if (item(); as currentItem) {
      <!-- currentItem is type-narrowed here -->
      <div>{{ currentItem.name }}</div>
      <div>{{ currentItem.description }}</div>
    }
  `
})
export class ItemComponent {
  item = signal<Item | null>(null);
}
2. @for - List Iteration

Basic @for Loop:

@Component({
  template: `
    <ul>
      @for (item of items(); track item.id) {
        <li>{{ item.name }}</li>
      }
    </ul>
  `
})
export class ListComponent {
  items = signal([
    { id: 1, name: 'Item 1' },
    { id: 2, name: 'Item 2' },
    { id: 3, name: 'Item 3' }
  ]);
}

@for with Index and Context:

@Component({
  template: `
    <div class="items">
      @for (item of items(); track item.id; let idx = $index, first = $first, last = $last) {
        <div class="item" [class.first]="first" [class.last]="last">
          <span class="index">{{ idx + 1 }}.</span>
          <span class="name">{{ item.name }}</span>
        </div>
      }
    </div>
  `
})
export class IndexedListComponent {
  items = signal<Item[]>([]);
}

Available Context Variables:

  • $index - Current index (0-based)
  • $first - True if first item
  • $last - True if last item
  • $even - True if even index
  • $odd - True if odd index
  • $count - Total number of items

@for with @empty:

@Component({
  template: `
    <div class="product-list">
      @for (product of products(); track product.id) {
        <app-product-card [product]="product" />
      } @empty {
        <div class="empty-state">
          <p>No products available</p>
          <button (click)="loadProducts()">Refresh</button>
        </div>
      }
    </div>
  `
})
export class ProductListComponent {
  products = signal<Product[]>([]);
}

Track By Best Practices:

// ✅ Good - Track by unique ID
@for (user of users(); track user.id) {
  <app-user-card [user]="user" />
}

// ✅ Good - Track by index for static lists
@for (tab of tabs; track $index) {
  <button>{{ tab }}</button>
}

// ❌ Bad - Track by object reference (will cause unnecessary re-renders)
@for (item of items(); track item) {
  <div>{{ item.name }}</div>
}
3. @switch - Multi-branch Conditionals

Basic @switch:

@Component({
  template: `
    @switch (userRole()) {
      @case ('admin') {
        <app-admin-panel />
      }
      @case ('moderator') {
        <app-moderator-panel />
      }
      @case ('user') {
        <app-user-panel />
      }
      @default {
        <app-guest-panel />
      }
    }
  `
})
export class RoleBasedComponent {
  userRole = signal<'admin' | 'moderator' | 'user' | 'guest'>('guest');
}

@switch with Complex Conditions:

@Component({
  template: `
    @switch (connectionStatus()) {
      @case ('connected') {
        <div class="status online">
          <mat-icon>check_circle</mat-icon>
          Connected
        </div>
      }
      @case ('connecting') {
        <div class="status pending">
          <mat-spinner diameter="20"></mat-spinner>
          Connecting...
        </div>
      }
      @case ('disconnected') {
        <div class="status offline">
          <mat-icon>error</mat-icon>
          Disconnected
        </div>
      }
      @case ('error') {
        <div class="status error">
          <mat-icon>warning</mat-icon>
          Connection Error
        </div>
      }
      @default {
        <div class="status unknown">Unknown Status</div>
      }
    }
  `
})
export class ConnectionStatusComponent {
  connectionStatus = signal<'connected' | 'connecting' | 'disconnected' | 'error'>('disconnected');
}
4. @defer - Lazy Loading and Code Splitting

Basic Deferred Loading:

@Component({
  template: `
    @defer {
      <app-heavy-component />
    } @placeholder {
      <div class="skeleton">Loading...</div>
    }
  `
})
export class DeferredComponent {}

Defer with Loading State:

@Component({
  template: `
    @defer {
      <app-video-player [src]="videoUrl" />
    } @loading (minimum 500ms) {
      <div class="loading-spinner">
        <mat-spinner></mat-spinner>
        <p>Loading video player...</p>
      </div>
    } @placeholder {
      <div class="video-placeholder">
        <mat-icon>play_circle</mat-icon>
      </div>
    } @error {
      <div class="error-state">
        <p>Failed to load video player</p>
        <button (click)="retry()">Retry</button>
      </div>
    }
  `
})
export class VideoComponent {
  videoUrl = signal('https://example.com/video.mp4');
}

Defer Triggers:

// Viewport trigger - Load when visible
@defer (on viewport) {
  <app-below-fold-content />
}

// Interaction trigger - Load on click
@defer (on interaction) {
  <app-modal-content />
}

// Idle trigger - Load when browser is idle
@defer (on idle) {
  <app-analytics-widget />
}

// Immediate trigger - Load immediately
@defer (on immediate) {
  <app-critical-content />
}

// Timer trigger - Load after delay
@defer (on timer(5s)) {
  <app-delayed-content />
}

// Hover trigger - Load on hover
@defer (on hover) {
  <app-tooltip-content />
}

// Combined triggers
@defer (on viewport; on idle) {
  <app-content />
}

Prefetching:

// Prefetch when idle
@defer (on viewport; prefetch on idle) {
  <app-article-content />
}

// Prefetch on hover
@defer (on interaction; prefetch on hover) {
  <app-modal />
}

Defer with Minimum Loading Time:

@Component({
  template: `
    @defer (on viewport) {
      <app-chart [data]="chartData()" />
    } @loading (minimum 1s) {
      <!-- Show loading for at least 1 second to avoid flashing -->
      <div class="chart-skeleton"></div>
    } @placeholder (minimum 500ms) {
      <!-- Show placeholder for at least 500ms -->
      <div class="chart-placeholder"></div>
    }
  `
})
export class ChartComponent {
  chartData = signal<ChartData[]>([]);
}

Migration from Old Syntax

ngIf → @if
// Before (Angular 19 and earlier)
<div *ngIf="isVisible">Content</div>
<div *ngIf="user; else loading">{{ user.name }}</div>

// After (Angular 20+)
@if (isVisible()) {
  <div>Content</div>
}

@if (user(); as currentUser) {
  <div>{{ currentUser.name }}</div>
} @else {
  <ng-container [ngTemplateOutlet]="loading" />
}
ngFor → @for
// Before
<li *ngFor="let item of items; trackBy: trackById">{{ item.name }}</li>

// After
@for (item of items(); track item.id) {
  <li>{{ item.name }}</li>
}
ngSwitch → @switch
// Before
<div [ngSwitch]="status">
  <div *ngSwitchCase="'success'">Success!</div>
  <div *ngSwitchCase="'error'">Error!</div>
  <div *ngSwitchDefault>Loading...</div>
</div>

// After
@switch (status()) {
  @case ('success') {
    <div>Success!</div>
  }
  @case ('error') {
    <div>Error!</div>
  }
  @default {
    <div>Loading...</div>
  }
}

Best Practices

1. Use Signals with Control Flow
// ✅ Good - Reactive with signals
export class Component {
  items = signal<Item[]>([]);
  isLoading = signal(false);
}

@Component({
  template: `
    @if (isLoading()) {
      <spinner />
    } @else {
      @for (item of items(); track item.id) {
        <item-card [item]="item" />
      }
    }
  `
})
2. Always Use track in @for
// ✅ Good - Proper tracking
@for (user of users(); track user.id) {
  <user-card [user]="user" />
}

// ❌ Bad - Missing track (will cause error)
@for (user of users()) {
  <user-card [user]="user" />
}

3. Leverage @defer for Performance

// ✅ Good - Defer heavy components
@defer (on viewport) {
  <app-complex-chart />
} @placeholder {
  <div class="chart-skeleton"></div>
}

// ✅ Good - Defer analytics
@defer (on idle) {
  <app-analytics-tracker />
}

4. Use @empty for Better UX

// ✅ Good - Handle empty state
@for (item of items(); track item.id) {
  <item-card [item]="item" />
} @empty {
  <empty-state message="No items found" />
}

5. Type Narrowing with @if

// ✅ Good - Type narrowing
@if (user(); as currentUser) {
  <!-- currentUser is guaranteed non-null here -->
  <div>{{ currentUser.email }}</div>
}

🔧 Advanced Patterns

Nested Control Flow

@Component({
  template: `
    @if (data(); as currentData) {
      @for (category of currentData.categories; track category.id) {
        <div class="category">
          <h3>{{ category.name }}</h3>
          @for (item of category.items; track item.id) {
            <div class="item">{{ item.title }}</div>
          } @empty {
            <p>No items in this category</p>
          }
        </div>
      }
    } @else {
      <app-loading />
    }
  `
})

Conditional Deferred Loading

@Component({
  template: `
    @if (shouldLoadHeavyComponent()) {
      @defer (on viewport) {
        <app-heavy-component [config]="config()" />
      } @loading {
        <skeleton-loader />
      }
    }
  `
})

🐛 Troubleshooting

IssueSolution
Syntax error with @ blocksEnsure Angular 20+ and update compiler
@for without track errorAlways add track expression to @for
@defer not lazy loadingCheck bundle config and verify component is in separate chunk
Type errors with @ifUse as alias for type narrowing
@empty not showingEnsure collection signal returns empty array, not undefined

📖 References


📂 Recommended Placement

Project-level skill:

/.github/skills/angular-20-control-flow/SKILL.md

Copilot will load this when working with Angular 20 control flow syntax.

平台分布

Antigravity

32.13%
按下载量换算65

OpenCode

25.6%
按下载量换算52

Claude Code

16.77%
按下载量换算34

Codex

11.88%
按下载量换算24

Gemini CLI

8.16%
按下载量换算16

windsurf

3.4%
按下载量换算7

安全审计

暂无安全审计结果可展示。

权限和风险

操作浏览器

该 Skill 可能涉及浏览器控制能力,使用时可能读取或操作网页内容,需要在受控环境中确认权限边界。

安装前确认

本站仅展示第三方公开信息,不托管安装包,不提供自动安装或运行环境。安装前应自行审查源码、依赖和命令行为。目前只有一个公开来源,建议同时核对源仓库。

继续浏览同类 Skills