Step 3: Overview page + filters + events

Add real data, reusable components, filters with query params, and event-driven updates.

In this step you will add real data, reusable components, query param syncing, and deep child-to-parent communication with the Event Aggregator.

1. Define shared models and data

Create src/models.ts:

export type Task = {
  id: string;
  title: string;
  done: boolean;
};

export type Project = {
  id: string;
  name: string;
  tasks: Task[];
};

Create src/project-data.ts:

import { Project } from './models';

export const PROJECTS: Project[] = [
  {
    id: 'alpha',
    name: 'Onboarding',
    tasks: [
      { id: 'alpha-1', title: 'Create welcome pack', done: false },
      { id: 'alpha-2', title: 'Schedule kickoff', done: false }
    ]
  },
  {
    id: 'beta',
    name: 'Release prep',
    tasks: [
      { id: 'beta-1', title: 'Finalize changelog', done: true },
      { id: 'beta-2', title: 'QA smoke test', done: false }
    ]
  }
];

2. Build reusable components

Create src/components/project-card.ts:

Create src/components/project-card.html:

The route: instruction uses a route id. Because this link lives inside the Overview child route, we prefix with ../ so the router resolves the id from the parent (Projects) route context.

Create src/components/task-list.ts:

Create src/components/task-list.html:

Create src/components/task-item.ts:

Create src/components/task-item.html:

3. Replace the Overview page with real behavior

Update src/pages/projects-overview-page.ts:

Update src/pages/projects-overview-page.html:

The loading hook reads the query params from next.queryParams. The Share Filter button uses IRouter.load() to update the URL.

4. Replace the Activity page with real data

Update src/pages/projects-activity-page.ts:

Update src/pages/projects-activity-page.html:

Next step: Step 4: Detail route + guards

Last updated

Was this helpful?