Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
import { TableComponent } from '@angular-challenges/shared/ui';
import { AsyncPipe } from '@angular/common';
import { ChangeDetectionStrategy, Component, Directive } from '@angular/core';
import {
ChangeDetectionStrategy,
Component,
Directive,
effect,
inject,
input,
} from '@angular/core';
import { CurrencyPipe } from './currency.pipe';
import { CurrencyService } from './currency.service';
import { Product, products } from './product.model';
Expand All @@ -22,9 +29,27 @@ export class ProductDirective {
}
}

@Component({
imports: [TableComponent, CurrencyPipe, AsyncPipe, ProductDirective],
@Directive({
selector: 'tr[currencyCode]',
Comment on lines +32 to +33

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '\n== File outline ==\n'
ast-grep outline apps/angular/16-master-dependency-injection/src/app/app.component.ts --view expanded || true

printf '\n== Relevant file excerpt ==\n'
cat -n apps/angular/16-master-dependency-injection/src/app/app.component.ts | sed -n '1,140p'

printf '\n== Search for directive selector lint config ==\n'
rg -n "`@angular-eslint/directive-selector`|directive-selector" -S . --glob '!**/node_modules/**' --glob '!**/dist/**' || true

printf '\n== Search for inline disables near the directive ==\n'
rg -n "eslint-disable|directive-selector|currencyCode" apps/angular/16-master-dependency-injection/src/app/app.component.ts -n -S || true

Repository: tomalaforge/angular-challenges

Length of output: 11889


🏁 Script executed:

#!/bin/bash
set -euo pipefail

cat -n apps/angular/16-master-dependency-injection/eslint.config.mjs

Repository: tomalaforge/angular-challenges

Length of output: 1098


Prefix the row directive selector to match the lint rule.
@angular-eslint/directive-selector here requires an app-prefixed attribute selector, so tr[currencyCode] will fail lint. Rename it to something like tr[appCurrencyCode] and update the template binding at line 66, or add a local disable if this exact selector is intentional.

🧰 Tools
🪛 ESLint

[error] 33-33: The selector should start with one of these prefixes: "app"

(@angular-eslint/directive-selector)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/angular/16-master-dependency-injection/src/app/app.component.ts` around
lines 32 - 33, The row directive selector in AppComponent does not follow the
Angular ESLint directive-selector convention, so update the `@Directive` selector
from the current attribute name to an app-prefixed one and keep the template
usage in sync. Fix the selector on the directive class in app.component.ts (the
directive that handles currency code rows) and update the matching binding
wherever it is used in the template so the selector and markup stay aligned; if
the selector must remain unchanged, add a local lint disable instead.

Source: Linters/SAST tools

providers: [CurrencyService],
})
export class ProductRowDirective {
#currencyService = inject(CurrencyService);
currencyCode = input.required<string>();

#syncCodeEffectRef = effect(() => {
this.#currencyService.patchState({ code: this.currencyCode() });
});
Comment on lines +40 to +42

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

git ls-files apps/angular/16-master-dependency-injection/src/app/app.component.ts && printf '\n---\n' && cat -n apps/angular/16-master-dependency-injection/src/app/app.component.ts

Repository: tomalaforge/angular-challenges

Length of output: 2772


🏁 Script executed:

rg -n "no-unused-private-class-members|EffectRef|effect\(" apps/angular/16-master-dependency-injection/src/app -S

Repository: tomalaforge/angular-challenges

Length of output: 278


Drop the unused EffectRef field. #syncCodeEffectRef is never read or destroyed, so it just trips no-unused-private-class-members. If you only need the side effect, create the effect without storing the ref.

🧰 Tools
🪛 ESLint

[error] 40-40: '#syncCodeEffectRef' is defined but never used.

(no-unused-private-class-members)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/angular/16-master-dependency-injection/src/app/app.component.ts` around
lines 40 - 42, The unused private EffectRef field in AppComponent should be
removed because it is only created and never read or destroyed. Update the
effect setup in the app component so the sync logic still runs via effect(() =>
...) but do not assign it to `#syncCodeEffectRef`, and keep the patchState call in
the effect body unchanged.

Source: Linters/SAST tools

}

@Component({
imports: [
TableComponent,
CurrencyPipe,
AsyncPipe,
ProductDirective,
ProductRowDirective,
],
selector: 'app-root',
template: `
<table [items]="products">
Expand All @@ -38,7 +63,7 @@ export class ProductDirective {
</tr>
</ng-template>
<ng-template #body product let-product>
<tr>
<tr [currencyCode]="product.currencyCode">
<td>{{ product.name }}</td>
<td>{{ product.priceA | currency | async }}</td>
<td>{{ product.priceB | currency | async }}</td>
Expand Down
3 changes: 2 additions & 1 deletion libs/shared/ui/src/lib/table.component.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import { NgTemplateOutlet } from '@angular/common';
import { Component, contentChild, input, TemplateRef } from '@angular/core';

@Component({
// eslint-disable-next-line @angular-eslint/component-selector
selector: 'table',
imports: [],
imports: [NgTemplateOutlet],
template: `
<thead>
<ng-container *ngTemplateOutlet="headerTemplate()"></ng-container>
Expand Down
Loading