mirror of
https://github.com/Raghu-Ch/angular-challenges.git
synced 2026-02-10 12:53:03 -05:00
feat: challenge 54 pipe obs signal (#903)
This commit is contained in:
@@ -24,7 +24,7 @@ If you would like to propose a challenge, this project is open source, so feel f
|
|||||||
|
|
||||||
## Challenges
|
## Challenges
|
||||||
|
|
||||||
Check [all 53 challenges](https://angular-challenges.vercel.app/)
|
Check [all 54 challenges](https://angular-challenges.vercel.app/)
|
||||||
|
|
||||||
## Contributors ✨
|
## Contributors ✨
|
||||||
|
|
||||||
|
|||||||
19
apps/signal/54-pipe-observable-to-signal/.eslintrc.json
Normal file
19
apps/signal/54-pipe-observable-to-signal/.eslintrc.json
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
{
|
||||||
|
"extends": ["../../../.eslintrc.json"],
|
||||||
|
"ignorePatterns": ["!**/*"],
|
||||||
|
"overrides": [
|
||||||
|
{
|
||||||
|
"files": ["*.ts"],
|
||||||
|
"extends": [
|
||||||
|
"plugin:@nx/angular",
|
||||||
|
"plugin:@angular-eslint/template/process-inline-templates"
|
||||||
|
],
|
||||||
|
"rules": {}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"files": ["*.html"],
|
||||||
|
"extends": ["plugin:@nx/angular-template"],
|
||||||
|
"rules": {}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
13
apps/signal/54-pipe-observable-to-signal/README.md
Normal file
13
apps/signal/54-pipe-observable-to-signal/README.md
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
# Pipe Observable to Signal
|
||||||
|
|
||||||
|
> author: thomas-laforge
|
||||||
|
|
||||||
|
### Run Application
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npx nx serve signal-pipe-observable-to-signal
|
||||||
|
```
|
||||||
|
|
||||||
|
### Documentation and Instruction
|
||||||
|
|
||||||
|
Challenge documentation is [here](https://angular-challenges.vercel.app/challenges/signal/54-pipe-observable-to-signal/).
|
||||||
72
apps/signal/54-pipe-observable-to-signal/project.json
Normal file
72
apps/signal/54-pipe-observable-to-signal/project.json
Normal file
@@ -0,0 +1,72 @@
|
|||||||
|
{
|
||||||
|
"name": "signal-pipe-observable-to-signal",
|
||||||
|
"$schema": "../../../node_modules/nx/schemas/project-schema.json",
|
||||||
|
"projectType": "application",
|
||||||
|
"prefix": "app",
|
||||||
|
"sourceRoot": "apps/signal/54-pipe-observable-to-signal/src",
|
||||||
|
"tags": [],
|
||||||
|
"targets": {
|
||||||
|
"build": {
|
||||||
|
"executor": "@angular-devkit/build-angular:application",
|
||||||
|
"outputs": ["{options.outputPath}"],
|
||||||
|
"options": {
|
||||||
|
"outputPath": "dist/apps/signal/54-pipe-observable-to-signal",
|
||||||
|
"index": "apps/signal/54-pipe-observable-to-signal/src/index.html",
|
||||||
|
"browser": "apps/signal/54-pipe-observable-to-signal/src/main.ts",
|
||||||
|
"polyfills": ["zone.js"],
|
||||||
|
"tsConfig": "apps/signal/54-pipe-observable-to-signal/tsconfig.app.json",
|
||||||
|
"inlineStyleLanguage": "scss",
|
||||||
|
"assets": [
|
||||||
|
"apps/signal/54-pipe-observable-to-signal/src/favicon.ico",
|
||||||
|
"apps/signal/54-pipe-observable-to-signal/src/assets"
|
||||||
|
],
|
||||||
|
"styles": ["apps/signal/54-pipe-observable-to-signal/src/styles.scss"],
|
||||||
|
"scripts": []
|
||||||
|
},
|
||||||
|
"configurations": {
|
||||||
|
"production": {
|
||||||
|
"budgets": [
|
||||||
|
{
|
||||||
|
"type": "initial",
|
||||||
|
"maximumWarning": "500kb",
|
||||||
|
"maximumError": "1mb"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "anyComponentStyle",
|
||||||
|
"maximumWarning": "2kb",
|
||||||
|
"maximumError": "4kb"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"outputHashing": "all"
|
||||||
|
},
|
||||||
|
"development": {
|
||||||
|
"optimization": false,
|
||||||
|
"extractLicenses": false,
|
||||||
|
"sourceMap": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"defaultConfiguration": "production"
|
||||||
|
},
|
||||||
|
"serve": {
|
||||||
|
"executor": "@angular-devkit/build-angular:dev-server",
|
||||||
|
"configurations": {
|
||||||
|
"production": {
|
||||||
|
"buildTarget": "signal-pipe-observable-to-signal:build:production"
|
||||||
|
},
|
||||||
|
"development": {
|
||||||
|
"buildTarget": "signal-pipe-observable-to-signal:build:development"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"defaultConfiguration": "development"
|
||||||
|
},
|
||||||
|
"extract-i18n": {
|
||||||
|
"executor": "@angular-devkit/build-angular:extract-i18n",
|
||||||
|
"options": {
|
||||||
|
"buildTarget": "signal-pipe-observable-to-signal:build"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"lint": {
|
||||||
|
"executor": "@nx/eslint:lint"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
import { TableComponent } from '@angular-challenges/shared/ui';
|
||||||
|
import { AsyncPipe } from '@angular/common';
|
||||||
|
import { ChangeDetectionStrategy, Component } from '@angular/core';
|
||||||
|
import { CurrencyPipe } from './currency.pipe';
|
||||||
|
import { ProductRowComponent } from './product-row.component';
|
||||||
|
import { products } from './product.model';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
standalone: true,
|
||||||
|
imports: [AsyncPipe, CurrencyPipe, TableComponent, ProductRowComponent],
|
||||||
|
selector: 'app-root',
|
||||||
|
template: `
|
||||||
|
<table [items]="products">
|
||||||
|
<ng-template #header>
|
||||||
|
<tr>
|
||||||
|
@for (col of displayedColumns; track col) {
|
||||||
|
<th>{{ col }}</th>
|
||||||
|
}
|
||||||
|
</tr>
|
||||||
|
</ng-template>
|
||||||
|
<ng-template #body let-product>
|
||||||
|
<tr product-row [product]="product"></tr>
|
||||||
|
</ng-template>
|
||||||
|
</table>
|
||||||
|
`,
|
||||||
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||||
|
})
|
||||||
|
export class AppComponent {
|
||||||
|
products = products;
|
||||||
|
displayedColumns = ['name', 'priceA', 'priceB', 'priceC'];
|
||||||
|
}
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
import { inject, Pipe, PipeTransform } from '@angular/core';
|
||||||
|
import { map, Observable } from 'rxjs';
|
||||||
|
import { CurrencyService } from './currency.service';
|
||||||
|
|
||||||
|
@Pipe({
|
||||||
|
name: 'currency',
|
||||||
|
standalone: true,
|
||||||
|
})
|
||||||
|
export class CurrencyPipe implements PipeTransform {
|
||||||
|
currencyService = inject(CurrencyService);
|
||||||
|
|
||||||
|
transform(price: number): Observable<string> {
|
||||||
|
return this.currencyService.symbol$.pipe(map((s) => `${price}${s}`));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
import { Injectable } from '@angular/core';
|
||||||
|
import { BehaviorSubject, map } from 'rxjs';
|
||||||
|
|
||||||
|
export interface Currency {
|
||||||
|
name: string;
|
||||||
|
code: string;
|
||||||
|
symbol: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const currency: Currency[] = [
|
||||||
|
{ name: 'Euro', code: 'EUR', symbol: '€' },
|
||||||
|
{ name: 'Dollar US', code: 'USD', symbol: 'US$' },
|
||||||
|
{ name: 'Dollar Autralien', code: 'AUD', symbol: 'AU$' },
|
||||||
|
{ name: 'Livre Sterling', code: 'GBP', symbol: '£' },
|
||||||
|
{ name: 'Dollar Canadien', code: 'CAD', symbol: 'CAD' },
|
||||||
|
];
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class CurrencyService {
|
||||||
|
private code = new BehaviorSubject('EUR');
|
||||||
|
|
||||||
|
readonly code$ = this.code.asObservable();
|
||||||
|
readonly symbol$ = this.code$.pipe(
|
||||||
|
map((code) => currency.find((c) => c.code === code)?.symbol ?? code),
|
||||||
|
);
|
||||||
|
|
||||||
|
public updateCode(code: string) {
|
||||||
|
this.code.next(code);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
import { AsyncPipe } from '@angular/common';
|
||||||
|
import {
|
||||||
|
ChangeDetectionStrategy,
|
||||||
|
Component,
|
||||||
|
inject,
|
||||||
|
Input,
|
||||||
|
} from '@angular/core';
|
||||||
|
import { CurrencyPipe } from './currency.pipe';
|
||||||
|
import { CurrencyService } from './currency.service';
|
||||||
|
import { Product } from './product.model';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
standalone: true,
|
||||||
|
selector: 'tr[product-row]',
|
||||||
|
template: `
|
||||||
|
<td>{{ productInfo.name }}</td>
|
||||||
|
<td>{{ productInfo.priceA | currency | async }}</td>
|
||||||
|
<td>{{ productInfo.priceB | currency | async }}</td>
|
||||||
|
<td>{{ productInfo.priceC | currency | async }}</td>
|
||||||
|
`,
|
||||||
|
imports: [AsyncPipe, CurrencyPipe],
|
||||||
|
providers: [CurrencyService],
|
||||||
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||||
|
})
|
||||||
|
export class ProductRowComponent {
|
||||||
|
protected productInfo!: Product;
|
||||||
|
|
||||||
|
@Input({ required: true }) set product(product: Product) {
|
||||||
|
this.currencyService.updateCode(product.currencyCode);
|
||||||
|
this.productInfo = product;
|
||||||
|
}
|
||||||
|
|
||||||
|
currencyService = inject(CurrencyService);
|
||||||
|
}
|
||||||
@@ -0,0 +1,55 @@
|
|||||||
|
export interface Product {
|
||||||
|
name: string;
|
||||||
|
priceA: number;
|
||||||
|
priceB: number;
|
||||||
|
priceC: number;
|
||||||
|
currencyCode: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const products: Product[] = [
|
||||||
|
{
|
||||||
|
name: 'bike',
|
||||||
|
priceA: 1000,
|
||||||
|
priceB: 2000,
|
||||||
|
priceC: 2200,
|
||||||
|
currencyCode: 'USD',
|
||||||
|
},
|
||||||
|
{ name: 'tent', priceA: 112, priceB: 120, priceC: 41, currencyCode: 'EUR' },
|
||||||
|
{
|
||||||
|
name: 'sofa',
|
||||||
|
priceA: 500,
|
||||||
|
priceB: 422,
|
||||||
|
priceC: 5000,
|
||||||
|
currencyCode: 'EUR',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'watch',
|
||||||
|
priceA: 50,
|
||||||
|
priceB: 130,
|
||||||
|
priceC: 150,
|
||||||
|
currencyCode: 'AUD',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'computer',
|
||||||
|
priceA: 1000,
|
||||||
|
priceB: 2200,
|
||||||
|
priceC: 3500,
|
||||||
|
currencyCode: 'GBP',
|
||||||
|
},
|
||||||
|
{ name: 'mug', priceA: 10, priceB: 15, priceC: 20, currencyCode: 'EUR' },
|
||||||
|
{
|
||||||
|
name: 'headset',
|
||||||
|
priceA: 100,
|
||||||
|
priceB: 150,
|
||||||
|
priceC: 220,
|
||||||
|
currencyCode: 'CAD',
|
||||||
|
},
|
||||||
|
{ name: 'cable', priceA: 5, priceB: 10, priceC: 15, currencyCode: 'EUR' },
|
||||||
|
{
|
||||||
|
name: 'table',
|
||||||
|
priceA: 100,
|
||||||
|
priceB: 20,
|
||||||
|
priceC: 500,
|
||||||
|
currencyCode: 'EUR',
|
||||||
|
},
|
||||||
|
];
|
||||||
BIN
apps/signal/54-pipe-observable-to-signal/src/favicon.ico
Normal file
BIN
apps/signal/54-pipe-observable-to-signal/src/favicon.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 15 KiB |
13
apps/signal/54-pipe-observable-to-signal/src/index.html
Normal file
13
apps/signal/54-pipe-observable-to-signal/src/index.html
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8" />
|
||||||
|
<title>signal-pipe-observable-to-signal</title>
|
||||||
|
<base href="/" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||||
|
<link rel="icon" type="image/x-icon" href="favicon.ico" />
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<app-root></app-root>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
4
apps/signal/54-pipe-observable-to-signal/src/main.ts
Normal file
4
apps/signal/54-pipe-observable-to-signal/src/main.ts
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
import { bootstrapApplication } from '@angular/platform-browser';
|
||||||
|
import { AppComponent } from './app/app.component';
|
||||||
|
|
||||||
|
bootstrapApplication(AppComponent).catch((err) => console.error(err));
|
||||||
26
apps/signal/54-pipe-observable-to-signal/src/styles.scss
Normal file
26
apps/signal/54-pipe-observable-to-signal/src/styles.scss
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
@tailwind base;
|
||||||
|
@tailwind components;
|
||||||
|
@tailwind utilities;
|
||||||
|
|
||||||
|
/* You can add global styles to this file, and also import other style files */
|
||||||
|
table {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
table thead > tr > th {
|
||||||
|
text-align: left;
|
||||||
|
padding: 1rem 1rem;
|
||||||
|
border: 1px solid #dee2e6;
|
||||||
|
border-width: 0 0 1px 0;
|
||||||
|
font-weight: 700;
|
||||||
|
color: #343a40;
|
||||||
|
background: #f8f9fa;
|
||||||
|
transition: box-shadow 0.2s;
|
||||||
|
}
|
||||||
|
|
||||||
|
table tbody > tr > td {
|
||||||
|
text-align: left;
|
||||||
|
border: 1px solid #dee2e6;
|
||||||
|
border-width: 0 0 1px 0;
|
||||||
|
padding: 1rem 1rem;
|
||||||
|
}
|
||||||
14
apps/signal/54-pipe-observable-to-signal/tailwind.config.js
Normal file
14
apps/signal/54-pipe-observable-to-signal/tailwind.config.js
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
const { createGlobPatternsForDependencies } = require('@nx/angular/tailwind');
|
||||||
|
const { join } = require('path');
|
||||||
|
|
||||||
|
/** @type {import('tailwindcss').Config} */
|
||||||
|
module.exports = {
|
||||||
|
content: [
|
||||||
|
join(__dirname, 'src/**/!(*.stories|*.spec).{ts,html}'),
|
||||||
|
...createGlobPatternsForDependencies(__dirname),
|
||||||
|
],
|
||||||
|
theme: {
|
||||||
|
extend: {},
|
||||||
|
},
|
||||||
|
plugins: [],
|
||||||
|
};
|
||||||
10
apps/signal/54-pipe-observable-to-signal/tsconfig.app.json
Normal file
10
apps/signal/54-pipe-observable-to-signal/tsconfig.app.json
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
{
|
||||||
|
"extends": "./tsconfig.json",
|
||||||
|
"compilerOptions": {
|
||||||
|
"outDir": "../../../dist/out-tsc",
|
||||||
|
"types": []
|
||||||
|
},
|
||||||
|
"files": ["src/main.ts"],
|
||||||
|
"include": ["src/**/*.d.ts"],
|
||||||
|
"exclude": ["jest.config.ts", "src/**/*.test.ts", "src/**/*.spec.ts"]
|
||||||
|
}
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"extends": "./tsconfig.json",
|
||||||
|
"include": ["src/**/*.ts"],
|
||||||
|
"compilerOptions": {},
|
||||||
|
"exclude": ["jest.config.ts", "src/**/*.test.ts", "src/**/*.spec.ts"]
|
||||||
|
}
|
||||||
30
apps/signal/54-pipe-observable-to-signal/tsconfig.json
Normal file
30
apps/signal/54-pipe-observable-to-signal/tsconfig.json
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"target": "es2022",
|
||||||
|
"useDefineForClassFields": false,
|
||||||
|
"esModuleInterop": true,
|
||||||
|
"forceConsistentCasingInFileNames": true,
|
||||||
|
"strict": true,
|
||||||
|
"noImplicitOverride": true,
|
||||||
|
"noPropertyAccessFromIndexSignature": true,
|
||||||
|
"noImplicitReturns": true,
|
||||||
|
"noFallthroughCasesInSwitch": true
|
||||||
|
},
|
||||||
|
"files": [],
|
||||||
|
"include": [],
|
||||||
|
"references": [
|
||||||
|
{
|
||||||
|
"path": "./tsconfig.editor.json"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "./tsconfig.app.json"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"extends": "../../../tsconfig.base.json",
|
||||||
|
"angularCompilerOptions": {
|
||||||
|
"enableI18nLegacyMessageIdFormat": false,
|
||||||
|
"strictInjectionParameters": true,
|
||||||
|
"strictInputAccessModifiers": true,
|
||||||
|
"strictTemplates": true
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"total": 53,
|
"total": 54,
|
||||||
"🟢": 21,
|
"🟢": 21,
|
||||||
"🟠": 122,
|
"🟠": 122,
|
||||||
"🔴": 209
|
"🔴": 210
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,7 +9,6 @@ challengeNumber: 53
|
|||||||
command: signal-big-signal-performance
|
command: signal-big-signal-performance
|
||||||
sidebar:
|
sidebar:
|
||||||
order: 122
|
order: 122
|
||||||
badge: New
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Information
|
## Information
|
||||||
|
|||||||
@@ -0,0 +1,22 @@
|
|||||||
|
---
|
||||||
|
title: 🔴 Pipe Observable to Signal
|
||||||
|
description: Challenge 54 is about refactoring an application using observable to signals
|
||||||
|
author: thomas-laforge
|
||||||
|
contributors:
|
||||||
|
- tomalaforge
|
||||||
|
challengeNumber: 54
|
||||||
|
command: signal-pipe-observable-to-signal
|
||||||
|
sidebar:
|
||||||
|
order: 210
|
||||||
|
badge: New
|
||||||
|
---
|
||||||
|
|
||||||
|
## Information
|
||||||
|
|
||||||
|
We have a legacy application that is using observables to store a state. Signals are a very good fit for that.
|
||||||
|
|
||||||
|
## Statement
|
||||||
|
|
||||||
|
So the goal of this challenge is to refactor the following application to be a fully signal based application.
|
||||||
|
|
||||||
|
Be careful along the way, everything might not work as you wish.
|
||||||
@@ -13,7 +13,7 @@ hero:
|
|||||||
icon: right-arrow
|
icon: right-arrow
|
||||||
variant: primary
|
variant: primary
|
||||||
- text: Ir al Desafío más reciente
|
- text: Ir al Desafío más reciente
|
||||||
link: /es/challenges/signal/53-big-signal-performance/
|
link: /es/challenges/signal/54-pipe-observable-to-signal/
|
||||||
icon: rocket
|
icon: rocket
|
||||||
- text: Dar una estrella
|
- text: Dar una estrella
|
||||||
link: https://github.com/tomalaforge/angular-challenges
|
link: https://github.com/tomalaforge/angular-challenges
|
||||||
@@ -26,8 +26,8 @@ import MyIcon from '../../../components/MyIcon.astro';
|
|||||||
import SubscriptionForm from '../../../components/SubscriptionForm.astro';
|
import SubscriptionForm from '../../../components/SubscriptionForm.astro';
|
||||||
|
|
||||||
<CardGrid>
|
<CardGrid>
|
||||||
<Card title="53 Desafíos">
|
<Card title="54 Desafíos">
|
||||||
Este repositorio contiene 53 Desafíos relacionados con <b>Angular</b>, <b>Nx</b>, <b>RxJS</b>, <b>Ngrx</b> y <b>Typescript</b>.
|
Este repositorio contiene 54 Desafíos relacionados con <b>Angular</b>, <b>Nx</b>, <b>RxJS</b>, <b>Ngrx</b> y <b>Typescript</b>.
|
||||||
Estos desafíos se resuelven en torno a problemas de la vida real o características específicas para mejorar tus habilidades.
|
Estos desafíos se resuelven en torno a problemas de la vida real o características específicas para mejorar tus habilidades.
|
||||||
</Card>
|
</Card>
|
||||||
|
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ hero:
|
|||||||
icon: right-arrow
|
icon: right-arrow
|
||||||
variant: primary
|
variant: primary
|
||||||
- text: Aller au dernier Challenge
|
- text: Aller au dernier Challenge
|
||||||
link: /fr/challenges/signal/53-big-signal-performance/
|
link: /fr/challenges/signal/54-pipe-observable-to-signal/
|
||||||
icon: rocket
|
icon: rocket
|
||||||
- text: Donne une étoile
|
- text: Donne une étoile
|
||||||
link: https://github.com/tomalaforge/angular-challenges
|
link: https://github.com/tomalaforge/angular-challenges
|
||||||
@@ -26,8 +26,8 @@ import MyIcon from '../../../components/MyIcon.astro';
|
|||||||
import SubscriptionForm from '../../../components/SubscriptionForm.astro';
|
import SubscriptionForm from '../../../components/SubscriptionForm.astro';
|
||||||
|
|
||||||
<CardGrid>
|
<CardGrid>
|
||||||
<Card title="53 Défis">
|
<Card title="54 Défis">
|
||||||
Ce répertoire rassemble 53 Défis liés à <b>Angular</b>, <b>Nx</b>, <b>RxJS</b>, <b>Ngrx</b> et <b>Typescript</b>. Ces défis portent sur des problèmes réels ou des fonctionnalités spécifiques pour améliorer vos compétences.
|
Ce répertoire rassemble 54 Défis liés à <b>Angular</b>, <b>Nx</b>, <b>RxJS</b>, <b>Ngrx</b> et <b>Typescript</b>. Ces défis portent sur des problèmes réels ou des fonctionnalités spécifiques pour améliorer vos compétences.
|
||||||
</Card>
|
</Card>
|
||||||
|
|
||||||
<Card title="Subscribe to get notify of latest challenges">
|
<Card title="Subscribe to get notify of latest challenges">
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ hero:
|
|||||||
icon: right-arrow
|
icon: right-arrow
|
||||||
variant: primary
|
variant: primary
|
||||||
- text: Ir para o desafio mais recente
|
- text: Ir para o desafio mais recente
|
||||||
link: /pt/challenges/signal/53-big-signal-performance/
|
link: /pt/challenges/signal/54-pipe-observable-to-signal/
|
||||||
icon: rocket
|
icon: rocket
|
||||||
- text: Dar uma estrela
|
- text: Dar uma estrela
|
||||||
link: https://github.com/tomalaforge/angular-challenges
|
link: https://github.com/tomalaforge/angular-challenges
|
||||||
@@ -26,8 +26,8 @@ import MyIcon from '../../../components/MyIcon.astro';
|
|||||||
import SubscriptionForm from '../../../components/SubscriptionForm.astro';
|
import SubscriptionForm from '../../../components/SubscriptionForm.astro';
|
||||||
|
|
||||||
<CardGrid>
|
<CardGrid>
|
||||||
<Card title="53 Desafios">
|
<Card title="54 Desafios">
|
||||||
Este repositório possui 53 Desafios relacionados a <b>Angular</b>, <b>Nx</b>, <b>RxJS</b>,
|
Este repositório possui 54 Desafios relacionados a <b>Angular</b>, <b>Nx</b>, <b>RxJS</b>,
|
||||||
<b>Ngrx</b> e <b>Typescript</b>.
|
<b>Ngrx</b> e <b>Typescript</b>.
|
||||||
Esses desafios são voltados para problemas reais ou funcionalidades específicas afim de
|
Esses desafios são voltados para problemas reais ou funcionalidades específicas afim de
|
||||||
melhorar suas habilidades.
|
melhorar suas habilidades.
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ hero:
|
|||||||
icon: right-arrow
|
icon: right-arrow
|
||||||
variant: primary
|
variant: primary
|
||||||
- text: Перейти к последней задаче
|
- text: Перейти к последней задаче
|
||||||
link: /ru/challenges/signal/53-big-signal-performance/
|
link: /ru/challenges/signal/54-pipe-observable-to-signal/
|
||||||
icon: rocket
|
icon: rocket
|
||||||
- text: Добавить звезду
|
- text: Добавить звезду
|
||||||
link: https://github.com/tomalaforge/angular-challenges
|
link: https://github.com/tomalaforge/angular-challenges
|
||||||
@@ -26,8 +26,8 @@ import MyIcon from '../../../components/MyIcon.astro';
|
|||||||
import SubscriptionForm from '../../../components/SubscriptionForm.astro';
|
import SubscriptionForm from '../../../components/SubscriptionForm.astro';
|
||||||
|
|
||||||
<CardGrid>
|
<CardGrid>
|
||||||
<Card title="53 испытаний">
|
<Card title="54 испытаний">
|
||||||
Этот репозиторий содержит 53 испытаний, связанных с <b>Angular</b>, <b>Nx</b>, <b>RxJS</b>, <b>Ngrx</b> и <b>Typescript</b>.
|
Этот репозиторий содержит 54 испытаний, связанных с <b>Angular</b>, <b>Nx</b>, <b>RxJS</b>, <b>Ngrx</b> и <b>Typescript</b>.
|
||||||
Испытания основаны на реальных задачах или инструментах для того, чтобы прокачать вас.
|
Испытания основаны на реальных задачах или инструментах для того, чтобы прокачать вас.
|
||||||
</Card>
|
</Card>
|
||||||
|
|
||||||
|
|||||||
@@ -1,21 +1,20 @@
|
|||||||
import { NgFor, NgTemplateOutlet } from '@angular/common';
|
import { NgTemplateOutlet } from '@angular/common';
|
||||||
import { Component, ContentChild, Input, TemplateRef } from '@angular/core';
|
import { Component, ContentChild, Input, TemplateRef } from '@angular/core';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'table',
|
selector: 'table',
|
||||||
standalone: true,
|
standalone: true,
|
||||||
imports: [NgTemplateOutlet, NgFor],
|
imports: [NgTemplateOutlet],
|
||||||
template: `
|
template: `
|
||||||
<thead>
|
<thead>
|
||||||
<ng-container *ngTemplateOutlet="headerTemplate"></ng-container>
|
<ng-container *ngTemplateOutlet="headerTemplate"></ng-container>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody *ngFor="let item of items">
|
@for (item of items; track $index) {
|
||||||
<ng-container
|
<tbody>
|
||||||
*ngTemplateOutlet="
|
<ng-container
|
||||||
bodyTemplate;
|
*ngTemplateOutlet="bodyTemplate; context: { $implicit: item }" />
|
||||||
context: { $implicit: item }
|
</tbody>
|
||||||
"></ng-container>
|
}
|
||||||
</tbody>
|
|
||||||
`,
|
`,
|
||||||
})
|
})
|
||||||
export class TableComponent<T> {
|
export class TableComponent<T> {
|
||||||
|
|||||||
Reference in New Issue
Block a user