کافه انگولار
133 subscribers
49 photos
7 files
39 links
توی کافه انگولار، Angular رو مثل روتین روزمره یاد می‌گیریم؛ پروژه‌محور، تمیز، و قابل استفاده تو کار واقعی
اینجا Performance مهمه
رو Best practice ها کار میکنیم

ادمین: @omidkhosrojerdi
لینکدین: linkedin.com/in/omidkhosrojerdi
Download Telegram
شاید براتون سؤال پیش اومده باشه که بین resource و rxResource و httpResource چه تفاوت‌هایی وجود داره؟

با چند تصویر و توضیح که این تفاوت هارو بیان میکنه همراه بشید

#angularcafe
4
Frontend Burger

لایه‌های مختلف کار‌هایی که یک Frontend developer در پروژه هاش انجام میده میتونه شامل این موارد باشه.

#angularcafe
🔥2😎2
https://ui.ng.guide/ui

x.com/katsuba_igor

یکی از توسعه دهنده های انگولار یه wrapper برای material 3 زده که هم signal first هست هم zoneless

و اینکه به نسبت خود سایت انگولار هم مستندات بهتری داره هم شخصی سازی بهتری میشه رو component ها داشت

بدون css framework و سبک درست شده

#angularmaterial
#angularsignal
#angularcafe
👍21👏1
کافه انگولار
Photo
با stable شدن API های Resource و httpResource برای مدیریت request‌ها، loading state و error state ها، برای component‌ها و service‌ها خیلی کاربردی شده.

ولی این API های جدید برای Router Guard و Resolver ها مناسب نیستن!

حالا چرا؟

چون ذاتا Guard‌ها و Resolver‌ها تا مشخص شدن نتیجه شون Navigation رو متوقف میکنن، یعنی باید منتظر یه نتیجه ای مثل Boolean، Promise یا Observable بمونن.

ولی Resource‌ها ذاتا Reactive هستن و وقتی داخل Resolver و یا Guard ازشون استفاده کنیم مقدار اولیه value شون معمولا undefined هست و request در وضعیت loading قرار داره و ما اگه همون لحظه بخوایم value شون رو استفاده کنیم اون Guard ممکنه سریعا مقدار false رو برگردونه و Navigation رو Cancel کنه حتی قبل از اینکه API اصلا جواب رو برگردونه!

export const authGuard: CanActivateFn = () => {
const authResource = httpResource<boolean>(() => ({
url: '/api/auth/status',
}));

// This returns the signal's current value synchronously
// Which is `undefined` initially!
return authResource.value() ?? false;
};



حالا راه درست چیه؟

برای Guard و Resolver فعلا همچنان از HttpClient و Observable یا Promise استفاده میکنیم که بشه از Async بودن شون این بهره رو برد تا جواب حاصل نشده، نتیجه ای برگردونده نشه قبل از Navigation کامل.

export const authGuard: CanActivateFn = () => {
const http = inject(HttpClient);

// An Observable cleanly blocks the Router until it completes or emits
return http.get<boolean>('/api/auth/status');
};



پس برای جمع‌بندی در حال حاضر Resource و httpResource برای UI و Reactive Data عالی هستن، اما برای Guard و Resolver درست هست که از همون روش‌های فعلی Observable و Promise استفاده کنیم.

در واقع Resource برای Data binding استفاده بشه و Observable و Promise برای Control flow در Routing پروژه.

#angularsignal
#angularcafe
👍4
کافه انگولار
Photo
خبر خوب اینکه تو Dialog در Angular Material 22 قابلیت input binding اضافه شده.

یعنی چی؟

قبلا برای پاس دادن مقادیری به Mat Dialog باید data رو پر میکردیم و داخل Component مورد نظر با inject کردن MAT_DIALOG_DATA اونو میگرفتید و استفاده میکردیم

حالا برای اینکه بتونیم از input و output و two-way binding استفاده کنیم قابلیت binding اضافه شده و میشه عین یه component که داخل html مینویسیم و بهش input و output پاس میدیم با component پاس داده شده به Dialog هم همون مدلی برخورد کنیم:

برای مثال:

code:
protected openSettingsDialog() {
this.dialog.open(NotificationSettingsComponent, {
width: '28rem',
panelClass: 'settings-dialog',
data: {user: this.user()}
});
}


و با گرفتن MAT_DIALOG_DATA اون دیتا رو استفاده میکردیم.

حالا با قابلیت binding میتونیم همچین چیزی انتظار داشته باشیم:

code:
<app-notification-settings
[user]="user()"
[(enabled)]="notificationsEnabled"
(saved)="saveNotificationSettings($event)"
/>


حالا چطوری؟

code:

protected openSettingsDialog() {
this.dialog.open(NotificationSettingsComponent, {
width: '28rem',
panelClass: 'settings-dialog',
bindings: [
inputBinding('user', this.user),
outputBinding<NotificationSettingsSaved>('saved', settings => {
this.saveNotificationSettings(settings);
}),
twoWayBinding('enabled', this.notificationsEnabled),
],
});
}


داخل component ای هم که داخل Dialog مد نظر داریم مثل حالت عادی signal input و outout و two-way رو استفاده میکنیم:

code:
export class NotificationSettingsComponent {
readonly user = input<User | null>(null);
readonly enabled = model(false);
readonly saved = output<NotificationSettingsSaved>();
protected save() {
if (this.user()) {
this.saved.emit({
userId: this.user()!.id,
enabled: this.enabled(),
});
}
}
}


منبع

#angularsignal
#angularcafe
3👏2
انگولار رو به روش صحیح به‌روزرسانی کنیم! 🚀

#angulartips
#angularcafe
👍6👏1
۱. مهاجرت‌های خودکار

ng generate @angular/core:signal-input-migration

ng generate @angular/core:output-migration

ng generate @angular/core:signal-queries-migration


۲. برای تبدیل Observableها از bridge مربوطه یعنی toSignal() استفاده کنید.

// Before
data$ = this.http.get(this.API_URL);
// Converting to Signal
data = toSignal(this.data$);


نمونه بالا مقدار اولیه رو undefined ست میکنه که میشه مثل نمونه زیر با initialValue مقداردهی اولیه کرد signal مون رو:

// Without default value
rates: Signal<Rates | undefined> = toSignal(this.rates$);
// With default value
rates: Signal<Rates> = toSignal(this.rates$,
{initialValue: {USD: 1, EUR: 1, GBP: 1}}
);


۳. تبدیل Subject‌ها به Signal:

// Subject version
currentCurrency = new BehaviorSubject<CurrencySymbol>(DEFAULT_CURRENCIES[0]);
// Signal version
currentCurrency = signal<CurrencySymbol>(DEFAULT_CURRENCIES[0]);


۴. جایگزین RXJS Operator‌ها با Computed:

// RxJs code
currentExchangeRate$ = combineLatest([
this.exchangeRates$,
this.currentCurrency$
]).pipe(
map(([rates, current]) => rates[current.code as keyof ExchangeRates])
);

// Equivalent Signal based version
currentExchangeRate = computed(
() => this.exchangeRates()[this.currentCurrency().code]
);


بعضی موقع‌ها، می‌خوایم بخشی از منطق RXJS رو نگه داریم چون خوب کار می‌کنه و از یه سری ویژگی‌هایی که معادل مستقیم مبتنی بر سیگنال ندارن مثل نمونه زیر که timer هست استفاده کنیم. تو این حالت، toSignal باز هم میتونه به عنوان یه Bridge عمل کنه و کل عملیات RX مون رو به signal تبدیل کنه:

// RxJs code
exchangeRates$: Observable<ExchangeRates> = timer(0, 3600000)
.pipe(
switchMap(() => this.http.get<any>(this.API_URL)),
map(data => ({
USD: 1,
EUR: data.rates.EUR,
GBP: data.rates.GBP
}))
);

// Simple Signal conversion with toSignal()
exchangeRates = toSignal(this.exchangeRates$);


نتیجه‌گیری به نظرم اینه که با جفت ویژگی ها تو صلح باشیم و از هرکدوم تو جای خودش استفاده کنیم و اگه از RXJS استفاده میکنیم از Memory leak جلوگیری کنیم و ازش اجتناب کنیم و البته که استفاده غیراصولی از Signal هم میتونه side effect‌های Memory leak داشته باشه ولی مدیریتش راحت‌تر از RX هست و همچنین لذت استفاده از signal به نظرم، باعث جلوگیری از استفاده چندین operator و کم کردن تعداد boilerplate‌های زیادی که قبلا مینوشتیم رو به ارمغان میاره برامون.

#angularsignal
#angularcafe
👍31
برای مدیریت Monorepo‌ها یه روش مرسوم NX هست که هنوزم خیلی فراگیر نشده بازم ولی یه Turborepo هم هست که شاید کمتر شنیده شده باشه که سرعت خیلی بالاتری نسبت به NX داره

اگه تجربه هرکدوم رو دارید باهامون به اشتراک بذارید

https://github.com/vercel/turborepo

https://github.com/nrwl/nx

#monorepo
#angularcafe
3👏1
اگه از Angular SSR نسخه +۲۰ استفاده میکنید حتما patch امنیتی جدید رو دریافت کنید

ریسک این باگ امنیتی High هست

دستور آپدیت پج در نسخه ۲۲
ng update @angular/core@22.0.7 @angular/cli@22.0.7


#angularssr
#angularcafe
👍5
https://uisfx.com/

یه کتابخانه کوچک و کامل پر از افکت‌های صوتی رابط کاربری برای interactive کردن UI تون که خیلی مدرن و باحال میکنه کارو

#angularcafe
👍4
3
https://namethatui.com/

اگه اسم یک سری Element‌های مورد استفاده در روزمره‌ تو کار‌هامون رو نمیدونین یا میخواستین دنبال یه آیتمی بگردین که اسم اش رو یادتون رفته این سایت میتونه گوشه ذهنتون باشه که هر کدوم از element‌ها اسم شون چیه و کاربرد‌شون چیه

#designtools
#angularcafe
1👍1
https://www.getlayers.ai/

یه سایت خفن که prompt های آماده فوق عجیب میده ولی پولی 🤒
ولی ایده هایش قشنگ هست میشه ایده ها رو بدی به AI و تا حدودی همون شکل پیاده‌ش کنه

#AI
#angularcafe
👍1
کافه انگولار
بیایید از تیریک هایی که باعث بشه اکانت Claude تون بن نشه بگید بقیه هم یاد بگیرن 👌
تجربه شخصیم:

با Apple gift card به اندازه پکیج Claude که میخواین خریداری کنید، حساب‌تون رو شارژ کنید

از VPN با IP ثابت استفاده کنید و ترجیحا آمریکا باشه
هر مقدار پکیج که میخواین خریداری کنید به اندازه ۱۰ درصد مالیات هم به کیف پول تون اضافه Gift card بزنید
20$ Claude +‌ 2$ Tax
125$ Claude +‌12.5$ Tax

چون من همون مقدار Claude رو شارژ کردم و موقع تکمیل کردن Transaction خطای Insufficient remaining credit میداد ولی نمیگه که چرا و باید Tax مثلا بخوره به Payment‌تون
پس حتما به اندازه Tax هم Gift card بریزید به حساب تون

سوال دیگه ای داشتید پیام بدید 👌🏾

#AI
#Claude
#angularcafe
👍3
https://procedural-sounds.vercel.app/

https://github.com/m1ckc3s/procedural-sounds

برای operation‌های سایت و پنل‌هامون اگه sound interaction اضافه کنیم بسیار جذاب و سرگرم کننده میشه در عین حال کاربردپذیری بیشتری هم داره

#sountkit
#angularcafe
👏3
https://sceneai.art/

دنیای طراحی سایت‌ها داره وارد یه عصر جدید میشه

دیگه ازون مدل های خسته کننده و بی روح داریم فاصله میگیریم

این سایت کلی prompt و ایده animation‌محور داره که میتونه بهمون کمک کنه از کارفرما ها پول بیشتری بگیریم 😁

#AI
#angularcafe
👏4
https://claudskills.com/

یه سایت فوق‌العاده برای پیدا کردن skills های Claude

بیش از ١٨٠ هزار skills مختلف

اگه استفاده کردید تجربه تون رو به اشتراک بذارید 👌

#AI
#angularcafe
3
https://www.youtube.com/watch?v=0bmUZsabKBs

این ویدیو رو ببینید که متوجه بشیم همگی توکن سوزی بیشتر به نوع درخواست prompt خودمون بستگی داره و از حالت پیشفرض خود AI استفاده کنیم کلی توکن سوزی اضافه رو دست مون میذاره

حتما سعی کنید markdown نوشتن prompt رو یاد بگیرید که به زبان خود AI باهاش صحبت کنید.

از AIهای دیگه مثل Gemini و GPT و Deepseek کمک بگیرید برای نوشتن prompt و زبان محاوره ای تون رو بهش بدید و ازش Markdown prompt بگیرید.

حتما از auto-translate استفاده کنید و فارسی رو انتخاب کنید تا مفاهیم بیشتر جا بیفته برامون 👌🏾

این نکته رو هم در نظر بگیرید که Agentها پرش های ذهنی زیادی دارن که اگه هدف رو درست بهشون ندیم و target و goal رو مشخص نکنیم جواب های پرتی بهمون میدن و توکن بیشتری میسوزونن.

#AI
#angularcafe
👏1
اگه می‌خواین همزمان از دو تا اکانت Claude AI روی دو تا VS Code جدا استفاده کنین و هر بار مجبور نباشین logout/login کنین، میشه یه setup تمیز براش ساخت.
مشکل اصلی اینه که اگه دو تا VS Code معمولی باز کنین، خیلی از تنظیمات، extensionها و حتی credentialهای Claude ممکنه مشترک باشن و باعث بشه اکانت‌ها با هم قاطی بشن.
راهی که استفاده کردم این بود که برای هر VS Code یه user-data-dir و extensions-dir جدا ساختم، بعد برای خود Claude هم با CLAUDE_CONFIG_DIR یه مسیر جدا برای config و credentialها تعریف کردم.
نتیجه این شد که عملاً دو تا محیط کاملاً مستقل دارم:
VS Code A → Claude Account A
VS Code B → Claude Account B
هرکدوم login، session، history، تنظیمات و extensionهای خودشون رو دارن و روی هم تأثیر نمی‌ذارن. اینطوری میشه همزمان روی دو پروژه مختلف با دو Claude account جدا کار کرد، بدون دردسر عوض کردن اکانت و بدون اینکه session یکی اون یکی رو خراب کنه.

اگه توضیح بیشتری نیاز داشتید نظر بذارید.

#claude_ai
#AI
#angularcafe
👏1👌1
https://ng-icons.github.io/ng-icons/

بالاخره بعد از مدت‌ها ظاهر ng-icons عوض شده و UX راحت‌تری هم داره
واقعا قبلی هم زشت بود هم UX سختی داشت

#angularcafe
👍1👏1