Merge pull request #3 from tomalaforge/main

merge upstream main
This commit is contained in:
Sagar Devkota
2023-11-24 08:56:03 +05:45
committed by GitHub
96 changed files with 319 additions and 136 deletions

View File

@@ -112,7 +112,8 @@
"avatar_url": "https://avatars.githubusercontent.com/u/30800393?v=4",
"profile": "http://www.sagardev.com.np",
"contributions": [
"doc"
"doc",
"code"
]
},
{

View File

@@ -45,7 +45,7 @@ Check [all 39 challenges](https://angular-challenges.vercel.app/)
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/DeveshChau"><img src="https://avatars.githubusercontent.com/u/9509673?v=4?s=100" width="100px;" alt="Devesh Chaudhari"/><br /><sub><b>Devesh Chaudhari</b></sub></a><br /><a href="https://github.com/tomalaforge/angular-challenges/commits?author=DeveshChau" title="Code">💻</a> <a href="https://github.com/tomalaforge/angular-challenges/issues?q=author%3ADeveshChau" title="Bug reports">🐛</a> <a href="#challenge-DeveshChau" title="Created a challenge">🧩</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/dmmishchenko"><img src="https://avatars.githubusercontent.com/u/51910160?v=4?s=100" width="100px;" alt="Dmitriy Mishchenko"/><br /><sub><b>Dmitriy Mishchenko</b></sub></a><br /><a href="https://github.com/tomalaforge/angular-challenges/commits?author=dmmishchenko" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="http://www.sagardev.com.np"><img src="https://avatars.githubusercontent.com/u/30800393?v=4?s=100" width="100px;" alt="Sagar Devkota"/><br /><sub><b>Sagar Devkota</b></sub></a><br /><a href="https://github.com/tomalaforge/angular-challenges/commits?author=Sagardevkota" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="http://www.sagardev.com.np"><img src="https://avatars.githubusercontent.com/u/30800393?v=4?s=100" width="100px;" alt="Sagar Devkota"/><br /><sub><b>Sagar Devkota</b></sub></a><br /><a href="https://github.com/tomalaforge/angular-challenges/commits?author=Sagardevkota" title="Documentation">📖</a> <a href="https://github.com/tomalaforge/angular-challenges/commits?author=Sagardevkota" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://nelsonguti.dev/"><img src="https://avatars.githubusercontent.com/u/62297014?v=4?s=100" width="100px;" alt="Nelson Gutierrez"/><br /><sub><b>Nelson Gutierrez</b></sub></a><br /><a href="https://github.com/tomalaforge/angular-challenges/commits?author=nelsongutidev" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/ho-ssain"><img src="https://avatars.githubusercontent.com/u/61125174?v=4?s=100" width="100px;" alt="Hossain K. M."/><br /><sub><b>Hossain K. M.</b></sub></a><br /><a href="https://github.com/tomalaforge/angular-challenges/commits?author=ho-ssain" title="Documentation">📖</a></td>
</tr>

View File

@@ -1,6 +1,6 @@
# Anchor Navigation
> Author: Thomas Laforge
> author: thomas-laforge
### Run Application

View File

@@ -1,6 +1,6 @@
# Change Detection Bug
> Author: Thomas Laforge
> author: thomas-laforge
### Run Application

View File

@@ -1,6 +1,6 @@
# Typed ContextOutlet
> Author: Thomas Laforge
> author: thomas-laforge
### Run Application

View File

@@ -1,6 +1,6 @@
# Crud application
> Author: Thomas Laforge
> author: thomas-laforge
### Run Application

View File

@@ -1,6 +1,6 @@
# Decoupling Components
> Author: Thomas Laforge
> author: thomas-laforge
### Run Application

View File

@@ -1,6 +1,6 @@
# Master Dependancy Injection
> Author: Thomas Laforge
> author: thomas-laforge
### Run Application

View File

@@ -1,6 +1,6 @@
# InjectionToken
> Author: Thomas Laforge
> author: thomas-laforge
### Run Application

View File

@@ -1,6 +1,6 @@
# Interoperability Rxjs/Signal
> Author: Thomas Laforge
> author: thomas-laforge
### Run Application

View File

@@ -1,6 +1,6 @@
# Module to Standalone
> Author: Thomas Laforge
> author: thomas-laforge
### Run Application

View File

@@ -1,6 +1,6 @@
# Directive Enhancement
> Author: Thomas Laforge
> author: thomas-laforge
### Run Application

View File

@@ -1,6 +1,6 @@
# Structural Directive
> Author: Thomas Laforge
> author: thomas-laforge
### Run Application

View File

@@ -1,6 +1,6 @@
# Pure Pipe
> Author: Thomas Laforge
> author: thomas-laforge
### Run Application

View File

@@ -1,6 +1,6 @@
# Utility Wrapper Pipe
> Author: Thomas Laforge
> author: thomas-laforge
### Run Application

View File

@@ -1,6 +1,6 @@
# Wrap Function Pipe
> Author: Thomas Laforge
> author: thomas-laforge
### Run Application

View File

@@ -1,6 +1,6 @@
# Projection
> Author: Thomas Laforge
> author: thomas-laforge
### Run Application

View File

@@ -1,6 +1,6 @@
# @RouterInput()
> Author: Thomas Laforge
> author: thomas-laforge
### Run Application

View File

@@ -1,6 +1,6 @@
# Highly Customizable CSS
> Author: Thomas Laforge
> author: thomas-laforge
### Run Application

View File

@@ -1,6 +1,6 @@
# Effect vs Selector
> Author: Thomas Laforge
> author: thomas-laforge
### Run Application

View File

@@ -1,6 +1,6 @@
# Power of Effect
> Author: Thomas Laforge
> author: thomas-laforge
### Run Application

View File

@@ -1,6 +1,6 @@
# Default vs OnPush
> Author: Thomas Laforge
> author: thomas-laforge
### Run Application

View File

@@ -1,6 +1,6 @@
# Memoization
> Author: Thomas Laforge
> author: thomas-laforge
### Run Application

View File

@@ -1,6 +1,6 @@
# NgFor optimize big list
> Author: Thomas Laforge
> author: thomas-laforge
### Run Application

View File

@@ -1,6 +1,6 @@
# NgFor Optimization
> Author: Thomas Laforge
> author: thomas-laforge
### Run Application

View File

@@ -1,6 +1,6 @@
# Optimize Change Detection
> Author: Thomas Laforge
> author: thomas-laforge
### Run Application

View File

@@ -1,6 +1,6 @@
# High Order Operator Bug
> Author: Thomas Laforge
> author: thomas-laforge
### Run Application

View File

@@ -1,6 +1,6 @@
# Race Condition
> Author: Thomas Laforge
> author: thomas-laforge
### Run Application

View File

@@ -1,6 +1,6 @@
# Checkbox
> Author: Thomas Laforge
> author: thomas-laforge
### Run Application

View File

@@ -1,6 +1,6 @@
# Harness Creation
> Author: Thomas Laforge
> author: thomas-laforge
### Run Application

View File

@@ -1,6 +1,6 @@
# Harness
> Author: Thomas Laforge
> author: thomas-laforge
### Run Application

View File

@@ -1,6 +1,6 @@
# Input Output
> Author: Thomas Laforge
> author: thomas-laforge
### Run Application

View File

@@ -1,6 +1,6 @@
# Modal
> Author: Thomas Laforge
> author: thomas-laforge
### Run Application

View File

@@ -1,6 +1,6 @@
# Nested Components
> Author: Thomas Laforge
> author: thomas-laforge
### Run Application

View File

@@ -1,6 +1,6 @@
# Router
> Author: Thomas Laforge
> author: thomas-laforge
### Run Application

View File

@@ -1,6 +1,6 @@
<h1>Table testing</h1>
> Author: Thomas Laforge
> author: thomas-laforge
## Statement:

View File

@@ -1,6 +1,6 @@
# Real-life Application
> Author: Thomas Laforge
> author: thomas-laforge
### Run Application

View File

@@ -1,6 +1,6 @@
# Function Overload
> Author: Thomas Laforge
> author: thomas-laforge
### Run Application

View File

@@ -0,0 +1,41 @@
---
import { Icon } from '@astrojs/starlight/components';
interface Props {
name: string;
twitter?: string;
linkedin?: string;
github?: string;
}
const { name, twitter, linkedin, github } = Astro.props;
---
<p class="author">
Created by {name}
{twitter && <a href={twitter}><Icon class='icon' name="twitter" size="0.75rem" /></a>}
{linkedin && <a href={linkedin}><Icon class='icon' name="linkedin" size="0.75rem" /></a>}
{github && <a href={github}><Icon class='icon' name="github" size="0.75rem" /></a>}
</p>
<style>
.author {
display: flex;
gap: 0.5rem;
align-items: center;
margin-top: -1rem;
font-size: var(--sl-text-xs);
color: var(--sl-color-gray-3);
}
.icon {
vertical-align: middle;
color: var(--sl-color-gray-3);
&:hover {
color: var(--sl-color-accent-high)
}
}
</style>

View File

@@ -1,5 +1,7 @@
---
import VideoButton from './VideoButton.astro'
import ClipboardCopy from './ClipboardCopy.astro'
const {author, challengeNumber, title, blogLink, videoLink, command} = Astro.props.entry.data;
@@ -7,14 +9,16 @@ const authorLink = `https://github.com/tomalaforge/angular-challenges/pulls?q=la
const authorDescription = `${title} solution author`;
const communityLink = `https://github.com/tomalaforge/angular-challenges/pulls?q=label%3A${challengeNumber}+label%3Aanswer`;
const communityDescription = `${title} community solutions`;
const npxCommand = `npx nx serve ${command}`;
---
<div class="separator"></div>
{command &&
{npxCommand &&
<aside aria-label="Note" class="starlight-aside starlight-aside--note"><p class="starlight-aside__title" aria-hidden="true"><svg viewBox="0 0 24 24" width="16" height="16" fill="currentColor" class="starlight-aside__icon"><path d="M12 11C11.7348 11 11.4804 11.1054 11.2929 11.2929C11.1054 11.4804 11 11.7348 11 12V16C11 16.2652 11.1054 16.5196 11.2929 16.7071C11.4804 16.8946 11.7348 17 12 17C12.2652 17 12.5196 16.8946 12.7071 16.7071C12.8946 16.5196 13 16.2652 13 16V12C13 11.7348 12.8946 11.4804 12.7071 11.2929C12.5196 11.1054 12.2652 11 12 11ZM12.38 7.08C12.1365 6.97998 11.8635 6.97998 11.62 7.08C11.4973 7.12759 11.3851 7.19896 11.29 7.29C11.2017 7.3872 11.1306 7.49882 11.08 7.62C11.024 7.73868 10.9966 7.86882 11 8C10.9992 8.13161 11.0245 8.26207 11.0742 8.38391C11.124 8.50574 11.1973 8.61656 11.29 8.71C11.3872 8.79833 11.4988 8.86936 11.62 8.92C11.7715 8.98224 11.936 9.00632 12.099 8.99011C12.2619 8.97391 12.4184 8.91792 12.5547 8.82707C12.691 8.73622 12.8029 8.61328 12.8805 8.46907C12.9582 8.32486 12.9992 8.16378 13 8C12.9963 7.73523 12.8927 7.48163 12.71 7.29C12.6149 7.19896 12.5028 7.12759 12.38 7.08ZM12 2C10.0222 2 8.08879 2.58649 6.4443 3.6853C4.79981 4.78412 3.51809 6.3459 2.76121 8.17317C2.00433 10.0004 1.8063 12.0111 2.19215 13.9509C2.578 15.8907 3.53041 17.6725 4.92894 19.0711C6.32746 20.4696 8.10929 21.422 10.0491 21.8079C11.9889 22.1937 13.9996 21.9957 15.8268 21.2388C17.6541 20.4819 19.2159 19.2002 20.3147 17.5557C21.4135 15.9112 22 13.9778 22 12C22 10.6868 21.7413 9.38642 21.2388 8.17317C20.7363 6.95991 19.9997 5.85752 19.0711 4.92893C18.1425 4.00035 17.0401 3.26375 15.8268 2.7612C14.6136 2.25866 13.3132 2 12 2ZM12 20C10.4178 20 8.87104 19.5308 7.55544 18.6518C6.23985 17.7727 5.21447 16.5233 4.60897 15.0615C4.00347 13.5997 3.84504 11.9911 4.15372 10.4393C4.4624 8.88743 5.22433 7.46197 6.34315 6.34315C7.46197 5.22433 8.88743 4.4624 10.4393 4.15372C11.9911 3.84504 13.5997 4.00346 15.0615 4.60896C16.5233 5.21447 17.7727 6.23984 18.6518 7.55544C19.5308 8.87103 20 10.4177 20 12C20 14.1217 19.1572 16.1566 17.6569 17.6569C16.1566 19.1571 14.1217 20 12 20Z"></path></svg>Note</p><section class="starlight-aside__content">
<p>Start the project by running: <code class="code" dir="auto">npx nx serve {command}</code>.</p></section></aside>
<p>Start the project by running: <code class="code" dir="auto">{npxCommand}
<ClipboardCopy copyText={npxCommand} />
</code></p></section></aside>
}
<aside aria-label="Reminder" class="starlight-aside starlight-aside--tip"><p class="starlight-aside__title" aria-hidden="true"><svg viewBox="0 0 24 24" width="16" height="16" fill="currentColor" class="starlight-aside__icon"><path fill-rule="evenodd" clip-rule="evenodd" d="M1.43909 8.85483L1.44039 8.85354L4.96668 5.33815C5.30653 4.99386 5.7685 4.79662 6.2524 4.78972L6.26553 4.78963L12.9014 4.78962L13.8479 3.84308C16.9187 0.772319 20.0546 0.770617 21.4678 0.975145C21.8617 1.02914 22.2271 1.21053 22.5083 1.4917C22.7894 1.77284 22.9708 2.13821 23.0248 2.53199C23.2294 3.94517 23.2278 7.08119 20.1569 10.1521L19.2107 11.0983V17.7338L19.2106 17.7469C19.2037 18.2308 19.0067 18.6933 18.6624 19.0331L15.1456 22.5608C14.9095 22.7966 14.6137 22.964 14.29 23.0449C13.9663 23.1259 13.6267 23.1174 13.3074 23.0204C12.9881 22.9235 12.7011 22.7417 12.4771 22.4944C12.2533 22.2473 12.1006 21.9441 12.0355 21.6171L11.1783 17.3417L6.65869 12.822L4.34847 12.3589L2.38351 11.965C2.05664 11.8998 1.75272 11.747 1.50564 11.5232C1.25835 11.2992 1.07653 11.0122 0.979561 10.6929C0.882595 10.3736 0.874125 10.034 0.955057 9.7103C1.03599 9.38659 1.20328 9.09092 1.43909 8.85483ZM6.8186 10.8724L2.94619 10.096L6.32006 6.73268H10.9583L6.8186 10.8724ZM15.2219 5.21703C17.681 2.75787 20.0783 2.75376 21.1124 2.8876C21.2462 3.92172 21.2421 6.31895 18.783 8.77812L12.0728 15.4883L8.51172 11.9272L15.2219 5.21703ZM13.9042 21.0538L13.1279 17.1811L17.2676 13.0414V17.68L13.9042 21.0538Z"></path><path d="M9.31827 18.3446C9.45046 17.8529 9.17864 17.3369 8.68945 17.1724C8.56178 17.1294 8.43145 17.1145 8.30512 17.1243C8.10513 17.1398 7.91519 17.2172 7.76181 17.3434C7.62613 17.455 7.51905 17.6048 7.45893 17.7835C6.97634 19.2186 5.77062 19.9878 4.52406 20.4029C4.08525 20.549 3.6605 20.644 3.29471 20.7053C3.35607 20.3395 3.45098 19.9148 3.59711 19.476C4.01221 18.2294 4.78141 17.0237 6.21648 16.5411C6.39528 16.481 6.54504 16.3739 6.65665 16.2382C6.85126 16.0016 6.92988 15.678 6.84417 15.3647C6.83922 15.3466 6.83373 15.3286 6.82767 15.3106C6.74106 15.053 6.55701 14.8557 6.33037 14.7459C6.10949 14.6389 5.84816 14.615 5.59715 14.6994C5.47743 14.7397 5.36103 14.7831 5.24786 14.8294C3.22626 15.6569 2.2347 17.4173 1.75357 18.8621C1.49662 19.6337 1.36993 20.3554 1.30679 20.8818C1.27505 21.1464 1.25893 21.3654 1.25072 21.5213C1.24662 21.5993 1.24448 21.6618 1.24337 21.7066L1.243 21.7226L1.24235 21.7605L1.2422 21.7771L1.24217 21.7827L1.24217 21.7856C1.24217 22.3221 1.67703 22.7579 2.2137 22.7579L2.2155 22.7579L2.22337 22.7578L2.23956 22.7577C2.25293 22.7575 2.27096 22.7572 2.29338 22.7567C2.33821 22.7555 2.40073 22.7534 2.47876 22.7493C2.63466 22.7411 2.85361 22.725 3.11822 22.6932C3.64462 22.6301 4.36636 22.5034 5.13797 22.2464C6.58274 21.7653 8.3431 20.7738 9.17063 18.7522C9.21696 18.639 9.26037 18.5226 9.30064 18.4029C9.30716 18.3835 9.31304 18.364 9.31827 18.3446Z"></path></svg>Reminder</p><section class="starlight-aside__content">
@@ -56,3 +60,4 @@ const communityDescription = `${title} community solutions`;
font-size: var(--sl-text-code-sm);
}
</style>

View File

@@ -0,0 +1,101 @@
---
const { copyText } = Astro.props;
---
<span class="copy-container">
<svg
aria-hidden="true"
focusable="false"
role="img"
class="copy-button"
viewBox="0 0 16 16"
width="16"
height="16"
style="display:inline-block;user-select:none;vertical-align:text-bottom;overflow:visible;"
fill="currentColor"
><path
d="M0 6.75C0 5.784.784 5 1.75 5h1.5a.75.75 0 0 1 0 1.5h-1.5a.25.25 0 0 0-.25.25v7.5c0 .138.112.25.25.25h7.5a.25.25 0 0 0 .25-.25v-1.5a.75.75 0 0 1 1.5 0v1.5A1.75 1.75 0 0 1 9.25 16h-7.5A1.75 1.75 0 0 1 0 14.25Z"
></path><path
d="M5 1.75C5 .784 5.784 0 6.75 0h7.5C15.216 0 16 .784 16 1.75v7.5A1.75 1.75 0 0 1 14.25 11h-7.5A1.75 1.75 0 0 1 5 9.25Zm1.75-.25a.25.25 0 0 0-.25.25v7.5c0 .138.112.25.25.25h7.5a.25.25 0 0 0 .25-.25v-7.5a.25.25 0 0 0-.25-.25Z"
></path></svg
>
<svg
style="display:none;user-select:none;vertical-align:text-bottom;overflow:visible;"
aria-hidden="true"
height="16"
viewBox="0 0 16 16"
version="1.1"
width="16"
data-view-component="true"
class="copied-checkmark"
><path
d="M13.78 4.22a.75.75 0 0 1 0 1.06l-7.25 7.25a.75.75 0 0 1-1.06 0L2.22 9.28a.751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018L6 10.94l6.72-6.72a.75.75 0 0 1 1.06 0Z"
></path></svg
>
<span class="tooltipText triangle">Copied!</span>
</span>
<script define:vars={{ copyText }}>
const commandCopyBtn = document.querySelector('.copy-button');
const copiedCheckMark = document.querySelector('.copied-checkmark');
const tooltipText = document.querySelector('.tooltipText');
commandCopyBtn.addEventListener('click', () => {
navigator.clipboard.writeText(copyText);
tooltipText.style.display = 'block';
copiedCheckMark.style.display = 'inline-block';
commandCopyBtn.style.display = 'none';
setTimeout(()=>{
copiedCheckMark.style.display = 'none';
commandCopyBtn.style.display = 'inline-block';
tooltipText.style.display = 'none';
}, 2000)
});
</script>
<style>
.copy-button {
margin-left: 0.5rem;
cursor: pointer;
}
.copy-button:hover{
fill: var(--sl-color-accent-high);
}
.copied-checkmark {
fill: var(--sl-color-green);
margin-left: 0.5rem;
display: none;
}
.copy-container {
position: relative;
}
.tooltipText {
position: absolute;
left: -14px;
width: max-content;
background-color: var(--sl-color-accent-high);
color: white;
display: none;
padding: 0.25rem 0.5rem;
border-radius: 0.25rem;
top: 200%;
font-size: 0.75rem;
}
.triangle:before {
content: "";
width: 0px;
height: 0px;
position: absolute;
border-left: 8px solid transparent;
border-right: 8px solid transparent;
border-bottom: 8px solid var(--sl-color-accent-high);
right: 28px;
top : -7px;
}
</style>

View File

@@ -1,15 +1,18 @@
---
import ChallengeFooter from './ChallengeFooter.astro'
import CommentSection from './CommentSection.astro'
import type { Props } from '@astrojs/starlight/props';
import Default from '@astrojs/starlight/components/MarkdownContent.astro';
import type { Props } from '@astrojs/starlight/props';
import { getEntry } from 'astro:content';
import Author from './Author.astro';
import ChallengeFooter from './ChallengeFooter.astro';
import CommentSection from './CommentSection.astro';
const {challengeNumber, author} = Astro.props.entry.data;
const {challengeNumber} = Astro.props.entry.data;
const author = Astro.props.entry.data.author ? await getEntry(Astro.props.entry.data.author) : null;
const renderCommentSection = !Astro.props.entry.data.noCommentSection;
---
{ challengeNumber && author && <p class="author">Created by {author}</p> }
{ challengeNumber && author && <Author {...author.data}/> }
<Default {...Astro.props}><slot /></Default>

View File

@@ -1,5 +1,11 @@
---
interface Props {
link: string;
alt: string;
flag?: 'FR';
}
const { link, alt, flag } = Astro.props;
const isFR = flag === 'FR';
---

View File

@@ -0,0 +1,4 @@
{
"name": "Devesh Chaudhari",
"twitter": "https://twitter.com/DeveshChau"
}

View File

@@ -0,0 +1,6 @@
{
"name": "Thomas Laforge",
"twitter": "https://twitter.com/laforge_toma",
"linkedin": "https://www.linkedin.com/in/thomas-laforge-2b05a945/",
"github": "https://github.com/tomalaforge"
}

View File

@@ -1,13 +1,22 @@
import { docsSchema, i18nSchema } from '@astrojs/starlight/schema';
import { defineCollection, z } from 'astro:content';
import { defineCollection, reference, z } from 'astro:content';
export const collections = {
docs: defineCollection({
const authors = defineCollection({
type: 'data',
schema: z.object({
name: z.string(),
twitter: z.string().url().optional(),
linkedin: z.string().url().optional(),
github: z.string().url().optional(),
}),
});
const docs = defineCollection({
schema: (ctx) =>
docsSchema()(ctx).extend({
noCommentSection: z.boolean().optional().default(false),
challengeNumber: z.union([z.number(), z.boolean()]).default(false),
author: z.string().optional(),
author: reference('authors').optional(),
command: z.string().optional(),
blogLink: z.string().optional(),
videoLink: z
@@ -18,6 +27,12 @@ export const collections = {
})
.optional(),
}),
}),
i18n: defineCollection({ type: 'data', schema: i18nSchema() }),
});
const i18n = defineCollection({ type: 'data', schema: i18nSchema() });
export const collections = {
docs: docs,
i18n: i18n,
authors: authors,
};

View File

@@ -1,7 +1,7 @@
---
title: 🟢 Projection
description: Challenge 1 is about learning how to project DOM element through components
author: Thomas Laforge
author: thomas-laforge
challengeNumber: 1
command: angular-projection
blogLink: https://medium.com/@thomas.laforge/create-a-highly-customizable-component-cc3a9805e4c5
@@ -15,7 +15,7 @@ sidebar:
## Information
In Angular, content projection is a powerful technique for creating highly customizable components. Utilizing and understanding the concepts of <b>ng-content</b> and <b>ngTemplateOutlet</b> can sighificantly enhance your ability to create shareable components.
In Angular, content projection is a powerful technique for creating highly customizable components. Utilizing and understanding the concepts of <b>ng-content</b> and <b>ngTemplateOutlet</b> can significantly enhance your ability to create shareable components.
You can learn all about <b>ng-content</b> [here](https://angular.io/guide/content-projection#projecting-content-in-more-complex-environments) from simple projection to more complex ones.

View File

@@ -1,7 +1,7 @@
---
title: 🔴 Utility Wrapper Pipe
description: Challenge 10 is about creating a pipe to wrap utilities
author: Thomas Laforge
author: thomas-laforge
challengeNumber: 10
command: angular-pipe-hard
sidebar:
@@ -12,13 +12,13 @@ sidebar:
WIP: The following documentation will be reviewed and improved. However, you can still take on the challenge. If you don't understand a certain part, please feel free to reach out or create an issue.
:::
The goal of this serie of 3 pipe challenges is to master PIPES in Angular.
The goal of this series of 3 pipe challenges is to master PIPES in Angular.
Pure pipe are a very useful way to transform data from your template. The difference between calling a function and a pipe is that pure pire are memoized. So they won't be recalculated every change detection cycle if the inputs hasn't changed.
Pure pipes are a very useful way to transform data from your template. The difference between calling a function and a pipe is that pure pipes are memoized. So they won't be recalculated every change detection cycle if their inputs haven't changed.
## Information:
In this third exercice, you want to access utils functions. Currently we cannot access them directly from your template. The goal is to create a specific pipe for this utils file where you will need to pass the name of the function you want to call and the needed arguments.
In this third exercice, you want to access utils functions. Currently you cannot access them directly from your template. The goal is to create a specific pipe for this utils file where you will need to pass the name of the function you want to call and the needed arguments.
## Constraints:

View File

@@ -1,7 +1,7 @@
---
title: 🟠 Highly Customizable CSS
description: Challenge 13 is about creating highly customizable CSS styles
author: Thomas Laforge
author: thomas-laforge
challengeNumber: 13
command: angular-styling
sidebar:

View File

@@ -1,7 +1,7 @@
---
title: 🔴 Master Dependancy Injection
description: Challenge 16 is about masjering how dependancy injection works
author: Thomas Laforge
author: thomas-laforge
challengeNumber: 16
command: angular-di
sidebar:

View File

@@ -1,7 +1,7 @@
---
title: 🟢 Anchor Navigation
description: Challenge 21 is about navigating inside the page with anchor
author: Thomas Laforge
author: thomas-laforge
challengeNumber: 21
command: angular-anchor-scrolling
sidebar:

View File

@@ -1,7 +1,7 @@
---
title: 🟢 @RouterInput()
description: Challenge 22 is about using the @Input decorator to retreive router params.
author: Thomas Laforge
author: thomas-laforge
challengeNumber: 22
command: angular-router-input
blogLink: https://medium.com/ngconf/accessing-route-params-in-angular-1f8e12770617

View File

@@ -1,7 +1,7 @@
---
title: 🟠 Directive Enhancement
description: Challenge 3 is about enhancing a built-in directive
author: Thomas Laforge
author: thomas-laforge
challengeNumber: 3
command: angular-ngfor-enhancement
blogLink: https://medium.com/@thomas.laforge/ngfor-enhancement-716b44656a6c

View File

@@ -1,7 +1,7 @@
---
title: 🔴 Interoperability Rxjs/Signal
description: Challenge 30 is about learning how to mix signal with Rxjs
author: Thomas Laforge
author: thomas-laforge
challengeNumber: 30
command: angular-interop-rxjs-signal
sidebar:

View File

@@ -1,7 +1,7 @@
---
title: 🟢 Module to Standalone
description: Challenge 31 is about migrating a module based application to a standalone application.
author: Thomas Laforge
author: thomas-laforge
challengeNumber: 31
command: angular-module-to-standalone
sidebar:

View File

@@ -1,7 +1,7 @@
---
title: 🟠 Change Detection Bug
description: Challenge 32 is about debugging an application that has issue when change detection is triggered
author: Thomas Laforge
author: thomas-laforge
challengeNumber: 32
command: angular-bug-cd
blogLink: https://medium.com/ngconf/function-calls-inside-template-are-dangerous-15f9822a6629

View File

@@ -1,7 +1,7 @@
---
title: 🟠 Decoupling Components
description: Challenge 33 is about decoupling two strongly coupled components using Injection Token
author: Thomas Laforge
author: thomas-laforge
challengeNumber: 33
command: angular-decoupling
sidebar:

View File

@@ -1,7 +1,7 @@
---
title: 🟠 InjectionToken
description: Challenge 39 is about learning the power of dependancy injection
author: Thomas Laforge
author: thomas-laforge
challengeNumber: 39
command: angular-injection-token
sidebar:

View File

@@ -1,7 +1,7 @@
---
title: 🔴 Typed ContextOutlet
description: Challenge 4 is about strongly typing ngContextOutlet directives
author: Thomas Laforge
author: thomas-laforge
challengeNumber: 4
command: angular-context-outlet-type
blogLink: https://medium.com/@thomas.laforge/ngtemplateoutlet-type-checking-5d2dcb07a2c6

View File

@@ -1,7 +1,7 @@
---
title: 🟢 Crud application
description: Challenge 5 is about refactoring a crud application
author: Thomas Laforge
author: thomas-laforge
challengeNumber: 5
command: angular-crud
sidebar:

View File

@@ -1,7 +1,7 @@
---
title: 🟠 Structural Directive
description: Challenge 6 is about creating a structural directive to handle permissions
author: Thomas Laforge
author: thomas-laforge
challengeNumber: 6
command: angular-permissions
blogLink: https://medium.com/@thomas.laforge/create-a-custom-structural-directive-to-manage-permissions-like-a-pro-11a1acad30ad

View File

@@ -1,7 +1,7 @@
---
title: 🟢 Pure Pipe
description: Challenge 8 is about creating a pure pipe
author: Thomas Laforge
author: thomas-laforge
challengeNumber: 8
command: angular-pipe-easy
blogLink: https://medium.com/ngconf/deep-dive-into-angular-pipes-c040588cd15d
@@ -13,13 +13,13 @@ sidebar:
WIP: The following documentation will be reviewed and improved. However, you can still take on the challenge. If you don't understand a certain part, please feel free to reach out or create an issue.
:::
The goal of this serie of 3 pipe challenges is to master PIPES in Angular.
The goal of this series of 3 pipe challenges is to master PIPES in Angular.
Pure pipe are a very useful way to transform data from your template. The difference between calling a function and a pipe is that pure pire are memoized. So they won't be recalculated every change detection cycle if the inputs hasn't changed.
Pure pipes are a very useful way to transform data from your template. The difference between calling a function and a pipe is that pure pipes are memoized. So they won't be recalculated every change detection cycle if their inputs haven't changed.
## Information:
In this first exercice, you add calling a simple function inside your template. The goal is to convert it to a pipe.
In this first exercice, you call a simple function inside your template. The goal is to convert it to a pipe.
## Constraints:

View File

@@ -1,7 +1,7 @@
---
title: 🟠 Wrap Function Pipe
description: Challenge 9 is about creating a pipe to wrap component fonctions
author: Thomas Laforge
author: thomas-laforge
challengeNumber: 9
command: angular-pipe-intermediate
blogLink: https://medium.com/ngconf/boost-your-apps-performance-by-wrapping-your-functions-inside-a-pipe-7e889a901d1d
@@ -15,9 +15,9 @@ WIP: The following documentation will be reviewed and improved. However, you can
<div class="chip">Challenge #9</div>
The goal of this serie of 3 pipe challenges is to master PIPES in Angular.
The goal of this series of 3 pipe challenges is to master PIPES in Angular.
Pure pipe are a very useful way to transform data from your template. The difference between calling a function and a pipe is that pure pire are memoized. So they won't be recalculated every change detection cycle if the inputs hasn't changed.
Pure pipes are a very useful way to transform data from your template. The difference between calling a function and a pipe is that pure pipes are memoized. So they won't be recalculated every change detection cycle if their inputs haven't changed.
## Information:

View File

@@ -1,7 +1,7 @@
---
title: 🟠 Effect vs Selector
description: Challenge 2 is about learning the difference between effects and selectors in NgRx
author: Thomas Laforge
author: thomas-laforge
challengeNumber: 2
command: ngrx-effect-selector
blogLink: https://medium.com/@thomas.laforge/ngrx-effect-vs-reducer-vs-selector-58337ab59043

View File

@@ -1,7 +1,7 @@
---
title: 🔴 Power of Effect
description: Challenge 7 is about creating an Ngrx effect with another Rxjs Hot observable
author: Thomas Laforge
author: thomas-laforge
challengeNumber: 7
command: ngrx-notification
sidebar:

View File

@@ -1,7 +1,7 @@
---
title: 🔴 Extend Lib Generator
description: Challenge 25 is about creating a Nx generator to extend the built-in Library Generator
author: Thomas Laforge
author: thomas-laforge
challengeNumber: 25
sidebar:
order: 207

View File

@@ -1,7 +1,7 @@
---
title: 🟠 Component Generator
description: Challenge 26 is about creating a Nx generator to create a custom component
author: Thomas Laforge
author: thomas-laforge
challengeNumber: 26
sidebar:
order: 116
@@ -88,7 +88,7 @@ export class UserStore extends ComponentStore<UserState> implements OnStateInit,
loading: this.loading$,
error: this.error$,
},
{ debounce: true }
{ debounce: true },
);
ngrxOnStateInit() {
@@ -106,11 +106,11 @@ export class UserStore extends ComponentStore<UserState> implements OnStateInit,
this.userService.loadUsers().pipe(
tapResponse(
(users) => this.patchState({ users, loading: false }),
(err: string) => this.patchState({ error: err, loading: false })
)
)
)
)
(err: string) => this.patchState({ error: err, loading: false }),
),
),
),
),
);
}
```

View File

@@ -1,7 +1,7 @@
---
title: 🟢 Custom Eslint Rule
description: Challenge 27 is about creating a custom Eslint Rule to forbid enums
author: Thomas Laforge
author: thomas-laforge
challengeNumber: 27
sidebar:
order: 12

View File

@@ -1,7 +1,7 @@
---
title: 🟠 Optimize Change Detection
description: Challenge 12 about optimizing the number of change detection cycle while scrolling
author: Thomas Laforge
author: thomas-laforge
challengeNumber: 12
command: performance-scroll-cd
sidebar:

View File

@@ -1,7 +1,7 @@
---
title: 🟢 Default vs OnPush
description: Challenge 34 is about learning the difference between Default and OnPush Change Detection Strategy.
author: Thomas Laforge
author: thomas-laforge
challengeNumber: 34
command: performance-default-onpush
sidebar:

View File

@@ -1,7 +1,7 @@
---
title: 🟢 Memoization
description: Challenge 35 is about learning how pure pipe works
author: Thomas Laforge
author: thomas-laforge
challengeNumber: 35
command: performance-memoized
sidebar:

View File

@@ -1,7 +1,7 @@
---
title: 🟢 NgFor Optimization
description: Challenge 36 is about learning how trackby works
author: Thomas Laforge
author: thomas-laforge
challengeNumber: 36
command: performance-ngfor-optimize
sidebar:

View File

@@ -1,7 +1,7 @@
---
title: 🟠 Optimize Big List
description: Challenge 37 is about learning how virtualization optimize big list rendering
author: Thomas Laforge
author: thomas-laforge
challengeNumber: 37
command: performance-ngfor-biglist
sidebar:

View File

@@ -1,9 +1,9 @@
---
title: 🟠 High Order Operator Bug
description: Challenge 11 is about resolving a Rxjs bug because of high order operators
author: Thomas Laforge
author: thomas-laforge
challengeNumber: 11
command: rxjs-pipe-bu
command: rxjs-pipe-bug
sidebar:
order: 114
---

View File

@@ -1,7 +1,7 @@
---
title: 🟢 Race Condition
description: Challenge 14 is about race condition in Rxjs
author: Thomas Laforge
author: thomas-laforge
challengeNumber: 14
command: rxjs-race-condition
sidebar:

View File

@@ -1,7 +1,7 @@
---
title: 🟢 catchError
description: Challenge 38 is about learning obervable completion.
author: Devesh Chaudhari
author: devesh-chaudhari
command: rxjs-catch-error
challengeNumber: 38
sidebar:

View File

@@ -1,7 +1,7 @@
---
title: 🟠 Router
description: Challenge 17 is about testing the router
author: Thomas Laforge
author: thomas-laforge
challengeNumber: 17
command: testing-router-outlet
sidebar:

View File

@@ -1,7 +1,7 @@
---
title: 🟠 Nested Components
description: Challenge 18 is about testing nested components
author: Thomas Laforge
author: thomas-laforge
challengeNumber: 18
command: testing-nested
sidebar:

View File

@@ -1,7 +1,7 @@
---
title: 🟠 Input Output
description: Challenge 19 is about testing inputs and ouputs
author: Thomas Laforge
author: thomas-laforge
challengeNumber: 19
command: testing-input-output
sidebar:

View File

@@ -1,7 +1,7 @@
---
title: 🟠 Modal
description: Challenge 20 is about testing modals
author: Thomas Laforge
author: thomas-laforge
challengeNumber: 20
command: testing-modal
sidebar:

View File

@@ -1,7 +1,7 @@
---
title: 🟢 Harness
description: Challenge 23 is about testing with component harnesses
author: Thomas Laforge
author: thomas-laforge
challengeNumber: 23
command: testing-harness
sidebar:

View File

@@ -1,7 +1,7 @@
---
title: 🟠 Harness Creation
description: Challenge 24 is about creating a component harness.
author: Thomas Laforge
author: thomas-laforge
challengeNumber: 24
command: testing-create-harness
sidebar:

View File

@@ -1,7 +1,7 @@
---
title: 🟢 Checkbox
description: Challenge 28 is about testing a simple checkbox
author: Thomas Laforge
author: thomas-laforge
challengeNumber: 28
command: testing-checkbox
sidebar:

View File

@@ -1,7 +1,7 @@
---
title: 🔴 Real-life Application
description: Challenge 29 is about testing a real-life application
author: Thomas Laforge
author: thomas-laforge
challengeNumber: 29
command: testing-todos-list
sidebar:

View File

@@ -1,7 +1,7 @@
---
title: 🟠 Function Overload
description: Challenge 15 is about creating overload functions
author: Thomas Laforge
author: thomas-laforge
challengeNumber: 15
command: typescript-overload
blogLink: https://medium.com/ngconf/function-overloading-in-typescript-8236706b2c05

View File

@@ -1,7 +1,7 @@
---
title: 🟢 Proyección
description: Desafio 1 trata sobre aprender a proyectar elementos del DOM a través de componentes,
author: Thomas Laforge
author: thomas-laforge
challengeNumber: 1
command: angular-projection
blogLink: https://medium.com/@thomas.laforge/create-a-highly-customizable-component-cc3a9805e4c5

View File

@@ -1,7 +1,7 @@
---
title: 🟠 InjectionToken
description: Desafio de Angular 39 para aprender sobre el poder del InjectionToken
author: Thomas Laforge
author: thomas-laforge
challengeNumber: 39
command: angular-injection-token
sidebar:

View File

@@ -17,4 +17,4 @@ You can contribute to this repository in many ways:
🔥 File an issue to suggest new challenge ideas or report a bug.
🔥 Sponsor the project [here](https://github.com/sponsors/tomalaforge)
🔥 Sponsor the project [here](https://github.com/sponsors/tomalaforge).

View File

@@ -10,7 +10,7 @@ sidebar:
Most of the time, this issue arises because your node_modules are outdated, and you need to update them by running `npm ci`.
If the installation process fails, you can resolve it by deleting your node_modules folder using the command `rm -rf node_modules` or `npx npkill` and then rerunning `npm ci`.
If the installation process fails, you can resolve it by deleting your node_modules folder using the command `rm -rf node_modules` or `npx npkill` and then re-running `npm ci`.
If the problem persists, please report the issue [here](https://github.com/tomalaforge/angular-challenges/issues/new).

View File

@@ -82,7 +82,7 @@ You can now click on <span class="github-success-btn">Create pull request</span>
I will read and comment on it <b>when I have some free time.</b>
<p class="important-block">Don't worry if your answer is not reviewed immediatly. I'm doing it for <b>free</b> and during my <b>free time</b>. If you want to support me, you can do so by <a href="https://github.com/sponsors/tomalaforge">sponsoring me on github</a>. It will validate that my work is of great help for you or your team.</p>
<p class="important-block">Don't worry if your answer is not reviewed immediately. I'm doing it for <b>free</b> and during my <b>free time</b>. If you want to support me, you can do so by <a href="https://github.com/sponsors/tomalaforge">sponsoring me on github</a>. It will validate that my work is of great help for you or your team.</p>
:::note
Everyone is welcome to comment and read other PRs.

View File

@@ -7,6 +7,7 @@
--primary-color: var(--sl-color-bg-nav) !important;
--cardBgColor: #242526;
--sl-color-green: #39a549;
--sl-hue-purple: 41;
--sl-color-purple-low: hsl(var(--sl-hue-orange), 39%, 22%);
--sl-color-purple: hsl(var(--sl-hue-orange), 82%, 63%);

View File

@@ -1,6 +1,6 @@
# <%= title %>
> Author: Thomas Laforge
> author: thomas-laforge
### Run Application

View File

@@ -23,7 +23,7 @@ function findDocFile(
tree: Tree,
path: string,
number: string,
result: string[]
result: string[],
) {
if (!tree.isFile(path)) {
tree.children(path).forEach((child) => {
@@ -59,13 +59,13 @@ async function rewriteFile(tree: Tree, file: string) {
tree,
'./docs/src/content/docs/challenges',
String(number),
result
result,
);
const docFile = result[0];
const pathElts = docFile.split('/');
const link = `https://angular-challenges.vercel.app/challenges/${pathElts.at(
-2
-2,
)}/${pathElts.at(-1)}/`;
const doc = tree.read(docFile);
@@ -89,7 +89,7 @@ async function rewriteFile(tree: Tree, file: string) {
const finalText = `# ${title}
> Author: Thomas Laforge
> author: thomas-laforge
### Run Application
@@ -154,14 +154,14 @@ Your PR title must start with <b>Answer:${number}</b>.
console.log('header', header);
const regexContent = new RegExp(
/Author: Thomas Laforge([\s\S]*?)### Submitting your work/
/author: thomas-laforge([\s\S]*?)### Submitting your work/,
);
const matchContent = buffer.toString().match(regexContent);
let content = '';
if (!matchContent) {
const regexOldContent = new RegExp(
/Author: Thomas Laforge([\s\S]*?)## Submitting your work/
/author: thomas-laforge([\s\S]*?)## Submitting your work/,
);
content = buffer.toString().match(regexOldContent)[1];
} else {

View File

@@ -1,6 +1,6 @@
# Extend Lib Generator
> Author: Thomas Laforge
> author: thomas-laforge
### Documentation and Instruction

View File

@@ -1,6 +1,6 @@
# Component Generator
> Author: Thomas Laforge
> author: thomas-laforge
### Documentation and Instruction

View File

@@ -1,6 +1,6 @@
# Custom Eslint Rule
> Author: Thomas Laforge
> author: thomas-laforge
### Run Application