[{"data":1,"prerenderedAt":1257},["ShallowReactive",2],{"article-\u002Farticles\u002F678fe3ea1a22a9426af87e0b":3},{"id":4,"title":5,"articleId":6,"body":7,"cover":1241,"coverThumb":1242,"created":1243,"date":1244,"description":1245,"extension":1246,"meta":1247,"navigation":372,"path":1248,"seo":1249,"stem":1250,"tags":1251,"updated":1255,"__hash__":1256},"articles\u002Farticles\u002F678fe3ea1a22a9426af87e0b.md","تحديث Angular 19 .. أهم ما يجب أن تعرفه عن التطورات الأخيرة","678fe3ea1a22a9426af87e0b",{"type":8,"value":9,"toc":1228},"minimark",[10,14,17,20,28,36,39,46,134,137,145,159,165,172,175,204,210,213,216,225,231,237,251,262,265,301,310,315,321,324,522,532,539,542,545,553,559,562,710,721,728,735,741,748,754,757,823,830,836,843,846,936,942,950,956,983,989,994,1000,1127,1130,1137,1142,1149,1152,1158,1207,1212,1215,1218,1221,1224],[11,12,13],"p",{},"الحمد لله الذي علَّم بالقلم، علَّم الإنسان ما لم يعلم، والصلاة والسلام على خير معلِّم الناس الخير سيدنا محمد - صلَّى الله عليه وسلم … أما بعد ،،",[11,15,16],{},"مؤخرًا أصدر فريق Angular الإصدار 19، الذي يقدم تحسينات مبتكرة تهدف إلى تعزيز تجربة المطورين وتحسين أداء التطبيقات بشكل فعال.",[11,18,19],{},"في هذا المقال، نستعرض هذه التحسينات والتطورات بأسلوب مبسط واحترافي، مع تسليط الضوء على أبرز الجوانب التي يمكنك الاستفادة منها في تحسين تطبيقاتك الحالية والمستقبلية - بمشيئة الله.",[21,22,24],"h2",{"id":23},"استقلال-المكوّنات-standalone-افتراضيا",[25,26,27],"strong",{},"استقلال المكوّنات (standalone) افتراضيا",[11,29,30,31,35],{},"بناء علي هذا التحديث أصبحت خاصية ",[32,33,34],"code",{},"standalone: true"," هي الإعداد الافتراضي للمكونات (components)، والموجهات (directives)، ومعالجات البيانات (pipes).",[11,37,38],{},"بعبارة أخري عند إنشاء مكون جديد، سيتم تعريفه تلقائيًا كمكون مستقل إلا إذا تم تحديد خلاف ذلك بشكل صريح، مما يساعد علي تبسيط عملية إنشاء المكونات وتقليل الأكواد المتكررة.",[11,40,41,42,45],{},"بالطبع، لا يزال بإمكانك كتابة مكونات تعتمد على NgModule من خلال تحديد ",[32,43,44],{},"standalone: false"," كما يلي:",[47,48,53],"pre",{"className":49,"code":50,"language":51,"meta":52,"style":52},"language-typescript shiki shiki-themes github-dark","@Component({\n  selector: 'home',\n  template: '.\u002Fhome-component.html',\n  standalone: false,  \u002F\u002F non-standalone in Angular 19!\n})\nexport class HomeComponent {…}\n","typescript","",[32,54,55,71,84,95,112,118],{"__ignoreMap":52},[56,57,60,64,68],"span",{"class":58,"line":59},"line",1,[56,61,63],{"class":62},"s95oV","@",[56,65,67],{"class":66},"svObZ","Component",[56,69,70],{"class":62},"({\n",[56,72,74,77,81],{"class":58,"line":73},2,[56,75,76],{"class":62},"  selector: ",[56,78,80],{"class":79},"sU2Wk","'home'",[56,82,83],{"class":62},",\n",[56,85,87,90,93],{"class":58,"line":86},3,[56,88,89],{"class":62},"  template: ",[56,91,92],{"class":79},"'.\u002Fhome-component.html'",[56,94,83],{"class":62},[56,96,98,101,105,108],{"class":58,"line":97},4,[56,99,100],{"class":62},"  standalone: ",[56,102,104],{"class":103},"sDLfK","false",[56,106,107],{"class":62},",  ",[56,109,111],{"class":110},"sAwPA","\u002F\u002F non-standalone in Angular 19!\n",[56,113,115],{"class":58,"line":114},5,[56,116,117],{"class":62},"})\n",[56,119,121,125,128,131],{"class":58,"line":120},6,[56,122,124],{"class":123},"snl16","export",[56,126,127],{"class":123}," class",[56,129,130],{"class":66}," HomeComponent",[56,132,133],{"class":62}," {…}\n",[11,135,136],{},"لتحديث تطبيقاتك الحالية لدعم هذا التعديل استخدم الأمر التالي",[47,138,143],{"className":139,"code":141,"language":142},[140],"language-text","ng generate @angular\u002Fcore:standalone\n","text",[32,144,141],{"__ignoreMap":52},[11,146,147,148,158],{},"وللمزيد من التفاصيل، يمكنك الرجوع إلى التوثيق الرسمي لهذه الميزة ",[149,150,157],"a",{"href":151,"rel":152,"target":156},"https:\u002F\u002Fangular.dev\u002Freference\u002Fmigrations\u002Fstandalone",[153,154,155],"nofollow","noopener","noreferrer","_blank","بالضغط هنا",".",[21,160,162],{"id":161},"التفعيل-التدريجي-incremental-hydration",[25,163,164],{},"التفعيل التدريجي (Incremental Hydration)",[11,166,167,168,171],{},"تتيح هذه الميزة إمكانية تحديد أجزاء معينة من القالب (template) باستخدام الصياغة المألوفة ",[32,169,170],{},"@defer","، مما يوجه Angular لتحميلها وتفعيلها بشكل مؤجل (Lazy load) استجابةً لمحفزات محددة.",[11,173,174],{},"يمكنك استخدام هذه الخاصية بالشكل التالي",[47,176,180],{"className":177,"code":178,"language":179,"meta":52,"style":52},"language-html shiki shiki-themes github-dark","@defer (hydrate on viewport) {\n  \u003Cblog-post\u002F>\n}\n","html",[32,181,182,187,199],{"__ignoreMap":52},[56,183,184],{"class":58,"line":59},[56,185,186],{"class":62},"@defer (hydrate on viewport) {\n",[56,188,189,192,196],{"class":58,"line":73},[56,190,191],{"class":62},"  \u003C",[56,193,195],{"class":194},"s4JwU","blog-post",[56,197,198],{"class":62},"\u002F>\n",[56,200,201],{"class":58,"line":86},[56,202,203],{"class":62},"}\n",[11,205,206,207,209],{},"وبالتالي عند تحميل التطبيق، لن يقوم Angular بتنزيل وتفعيل مكون ",[32,208,195],{}," إلا عند دخوله إلى منطقة العرض (viewport).",[11,211,212],{},"هذا الأسلوب يسهم في تحسين الأداء من خلال تأجيل تحميل الأجزاء غير الضرورية الي حين الحاجة إليها.",[11,214,215],{},"يرجي العلم أن هذه الخاصية ما زالت قيد التطوير والمراجعة، ومن الوارد أن تتغير أو يتم استبدالها مستقبلا.",[11,217,218,219,224],{},"لمعرفة المزيد ",[149,220,223],{"href":221,"rel":222,"target":156},"https:\u002F\u002Fangular.dev\u002Fguide\u002Fincremental-hydration",[153,154,155],"أضغط هنا"," لزيارة التوثيق الرسمي لهذه الخاصية.",[21,226,228],{"id":227},"الإشارات-signals",[25,229,230],{},"الإشارات (Signals)",[11,232,233],{},[234,235],"img",{"alt":52,"src":236},"\u002Fimages\u002F678feb281a22a9426af87e45.webp",[11,238,239,240,243,244,243,247,250],{},"وفقا لهذا التحديث، فإن الإشارات مثل ",[25,241,242],{},"Input"," و",[25,245,246],{},"Model",[25,248,249],{},"Output"," ... وغيرها، أصبحت الآن مستقرة ويمكنك استخدامها بشكل طبيعي.",[252,253,254],"blockquote",{},[11,255,256,257,261],{},"يمكنك الإطلاع علي مقالي السابق (",[149,258,260],{"href":259},"\u002Farticles\u002F6703caeaf1aaf592bac7544e\u002F","دليلك لفهم Angular Signals بأسلوب مُبسَّط",") الذي يوضح كيف ساهمت Signals في إحداث نقلة نوعية في Angular من خلال تحسين أداء التطبيقات.",[11,263,264],{},"بدلا من المرور بشكل يدوي علي جميع الأكواد القديمة في تطبيقك مثل @Input واستبدالها بInput المبنية على الإشارات، يمكنك استخدام أوامر جاهزة تم إعدادها مسبقا، كما يلي:",[47,266,270],{"className":267,"code":268,"language":269,"meta":52,"style":52},"language-bash shiki shiki-themes github-dark","ng generate @angular\u002Fcore:signal-input-migration\nng generate @angular\u002Fcore:signal-queries-migration\nng generate @angular\u002Fcore:output-migration\n","bash",[32,271,272,283,292],{"__ignoreMap":52},[56,273,274,277,280],{"class":58,"line":59},[56,275,276],{"class":66},"ng",[56,278,279],{"class":79}," generate",[56,281,282],{"class":79}," @angular\u002Fcore:signal-input-migration\n",[56,284,285,287,289],{"class":58,"line":73},[56,286,276],{"class":66},[56,288,279],{"class":79},[56,290,291],{"class":79}," @angular\u002Fcore:signal-queries-migration\n",[56,293,294,296,298],{"class":58,"line":86},[56,295,276],{"class":66},[56,297,279],{"class":79},[56,299,300],{"class":79}," @angular\u002Fcore:output-migration\n",[11,302,303,304,309],{},"ولو كنت تستخدم الإضافة (",[149,305,308],{"href":306,"rel":307,"target":156},"https:\u002F\u002Fmarketplace.visualstudio.com\u002Fitems?itemName=Angular.ng-template",[153,154,155],"Angular Language Service",") في برنامج VSCode يمكنك إجراء نفس التعديل كما في الصورة التالية",[11,311,312],{},[234,313],{"alt":52,"src":314},"\u002Fimages\u002F678fe5861a22a9426af87e2c.webp",[21,316,318],{"id":317},"الإشارات-المرتبطة-linked-signals",[25,319,320],{},"الإشارات المرتبطة (Linked Signals)",[11,322,323],{},"تتيح هذه الميزة طريقة سهلة لإدارة الحالات التي تعتمد على حالات أخرى، فهي تبسط عملية ربط الحالات معًا دون الحاجة إلى استخدام حلول معقدة، مما يجعل إدارة الحالة أكثر وضوحًا وسلاسة.",[47,325,327],{"className":49,"code":326,"language":51,"meta":52,"style":52},"\u002F\u002F List of available products\nconst products = signal(['Laptop', 'Tablet', 'Smartphone']);\n\n\u002F\u002F Selected product, defaults to the first item\nconst selectedProduct = linkedSignal(() => products()[0]);\nconsole.log(selectedProduct()); \u002F\u002F Laptop\n\n\u002F\u002F Manually change selected product\nselectedProduct.set('Smartphone');\nconsole.log(selectedProduct()); \u002F\u002F Smartphone\n\n\u002F\u002F Reset to first item when products list updates\nproducts.set(['Monitor', 'Keyboard', 'Mouse']);\nconsole.log(selectedProduct()); \u002F\u002F Monitor\n",[32,328,329,334,368,374,379,407,427,432,438,454,470,475,481,506],{"__ignoreMap":52},[56,330,331],{"class":58,"line":59},[56,332,333],{"class":110},"\u002F\u002F List of available products\n",[56,335,336,339,342,345,348,351,354,357,360,362,365],{"class":58,"line":73},[56,337,338],{"class":123},"const",[56,340,341],{"class":103}," products",[56,343,344],{"class":123}," =",[56,346,347],{"class":66}," signal",[56,349,350],{"class":62},"([",[56,352,353],{"class":79},"'Laptop'",[56,355,356],{"class":62},", ",[56,358,359],{"class":79},"'Tablet'",[56,361,356],{"class":62},[56,363,364],{"class":79},"'Smartphone'",[56,366,367],{"class":62},"]);\n",[56,369,370],{"class":58,"line":86},[56,371,373],{"emptyLinePlaceholder":372},true,"\n",[56,375,376],{"class":58,"line":97},[56,377,378],{"class":110},"\u002F\u002F Selected product, defaults to the first item\n",[56,380,381,383,386,388,391,394,397,399,402,405],{"class":58,"line":114},[56,382,338],{"class":123},[56,384,385],{"class":103}," selectedProduct",[56,387,344],{"class":123},[56,389,390],{"class":66}," linkedSignal",[56,392,393],{"class":62},"(() ",[56,395,396],{"class":123},"=>",[56,398,341],{"class":66},[56,400,401],{"class":62},"()[",[56,403,404],{"class":103},"0",[56,406,367],{"class":62},[56,408,409,412,415,418,421,424],{"class":58,"line":120},[56,410,411],{"class":62},"console.",[56,413,414],{"class":66},"log",[56,416,417],{"class":62},"(",[56,419,420],{"class":66},"selectedProduct",[56,422,423],{"class":62},"()); ",[56,425,426],{"class":110},"\u002F\u002F Laptop\n",[56,428,430],{"class":58,"line":429},7,[56,431,373],{"emptyLinePlaceholder":372},[56,433,435],{"class":58,"line":434},8,[56,436,437],{"class":110},"\u002F\u002F Manually change selected product\n",[56,439,441,444,447,449,451],{"class":58,"line":440},9,[56,442,443],{"class":62},"selectedProduct.",[56,445,446],{"class":66},"set",[56,448,417],{"class":62},[56,450,364],{"class":79},[56,452,453],{"class":62},");\n",[56,455,457,459,461,463,465,467],{"class":58,"line":456},10,[56,458,411],{"class":62},[56,460,414],{"class":66},[56,462,417],{"class":62},[56,464,420],{"class":66},[56,466,423],{"class":62},[56,468,469],{"class":110},"\u002F\u002F Smartphone\n",[56,471,473],{"class":58,"line":472},11,[56,474,373],{"emptyLinePlaceholder":372},[56,476,478],{"class":58,"line":477},12,[56,479,480],{"class":110},"\u002F\u002F Reset to first item when products list updates\n",[56,482,484,487,489,491,494,496,499,501,504],{"class":58,"line":483},13,[56,485,486],{"class":62},"products.",[56,488,446],{"class":66},[56,490,350],{"class":62},[56,492,493],{"class":79},"'Monitor'",[56,495,356],{"class":62},[56,497,498],{"class":79},"'Keyboard'",[56,500,356],{"class":62},[56,502,503],{"class":79},"'Mouse'",[56,505,367],{"class":62},[56,507,509,511,513,515,517,519],{"class":58,"line":508},14,[56,510,411],{"class":62},[56,512,414],{"class":66},[56,514,417],{"class":62},[56,516,420],{"class":66},[56,518,423],{"class":62},[56,520,521],{"class":110},"\u002F\u002F Monitor\n",[11,523,524,525,528,529,531],{},"في هذا المثال، لدينا قائمة من المنتجات محفوظة داخل إشارة (signal) تسمى ",[32,526,527],{},"products","، وهناك إشارة مرتبطة (linked signal) اسمها ",[32,530,420],{}," تقوم بتحديد المنتج الافتراضي بناءً على العنصر الأول في القائمة.",[11,533,534,535,538],{},"يمكننا تغيير المنتج المختار يدويًا باستخدام ",[32,536,537],{},"set()","، أو تحديث قائمة المنتجات بالكامل.",[11,540,541],{},"عند تحديث قائمة المنتجات، يتم إعادة تعيين المنتج المختار تلقائيًا ليصبح العنصر الأول في القائمة الجديدة.",[11,543,544],{},"هذا الأسلوب يجعل إدارة الحالة ديناميكية وسهلة، حيث تتغير القيم تلقائيًا بناءً على التحديثات في القائمة الأصلية.",[11,546,547,548,552],{},"يجدر الإشارة هنا إلي أن هذه الخاصية ما زالت أيضا قيد التطوير والمراجعة، فضلا ",[149,549,223],{"href":550,"rel":551,"target":156},"https:\u002F\u002Fangular.dev\u002Fguide\u002Fsignals\u002Flinked-signal",[153,154,155]," للإطلاع علي معلومات أكثر علي التوثيق الرسمي.",[21,554,556],{"id":555},"واجهة-الموارد-resource-api",[25,557,558],{},"واجهة الموارد (Resource API)",[11,560,561],{},"هي طريقة سهلة لإدارة جلب البيانات وحفظها، إذ تساعد في تبسيط التعامل مع البيانات غير المتزامنة وتُقلل من الحاجة لكتابة أكواد مكررة عند العمل مع البيانات.",[47,563,565],{"className":49,"code":564,"language":51,"meta":52,"style":52},"@Component(...)\nexport class WeatherComponent {\n  city = input\u003Cstring>();\n\n  weatherService = inject(WeatherService);\n\n  weatherData = resource({\n    request: this.city,\n    loader: async ({ request: cityName }) => \n      await weatherService.getWeather(cityName),\n  });\n}\n",[32,566,567,581,593,613,617,630,634,646,657,687,701,706],{"__ignoreMap":52},[56,568,569,571,573,575,578],{"class":58,"line":59},[56,570,63],{"class":62},[56,572,67],{"class":66},[56,574,417],{"class":62},[56,576,577],{"class":123},"...",[56,579,580],{"class":62},")\n",[56,582,583,585,587,590],{"class":58,"line":73},[56,584,124],{"class":123},[56,586,127],{"class":123},[56,588,589],{"class":66}," WeatherComponent",[56,591,592],{"class":62}," {\n",[56,594,595,599,601,604,607,610],{"class":58,"line":86},[56,596,598],{"class":597},"s9osk","  city",[56,600,344],{"class":123},[56,602,603],{"class":66}," input",[56,605,606],{"class":62},"\u003C",[56,608,609],{"class":103},"string",[56,611,612],{"class":62},">();\n",[56,614,615],{"class":58,"line":97},[56,616,373],{"emptyLinePlaceholder":372},[56,618,619,622,624,627],{"class":58,"line":114},[56,620,621],{"class":597},"  weatherService",[56,623,344],{"class":123},[56,625,626],{"class":66}," inject",[56,628,629],{"class":62},"(WeatherService);\n",[56,631,632],{"class":58,"line":120},[56,633,373],{"emptyLinePlaceholder":372},[56,635,636,639,641,644],{"class":58,"line":429},[56,637,638],{"class":597},"  weatherData",[56,640,344],{"class":123},[56,642,643],{"class":66}," resource",[56,645,70],{"class":62},[56,647,648,651,654],{"class":58,"line":434},[56,649,650],{"class":62},"    request: ",[56,652,653],{"class":103},"this",[56,655,656],{"class":62},".city,\n",[56,658,659,662,665,668,671,674,676,679,682,684],{"class":58,"line":440},[56,660,661],{"class":66},"    loader",[56,663,664],{"class":62},": ",[56,666,667],{"class":123},"async",[56,669,670],{"class":62}," ({ ",[56,672,673],{"class":597},"request",[56,675,664],{"class":62},[56,677,678],{"class":597},"cityName",[56,680,681],{"class":62}," }) ",[56,683,396],{"class":123},[56,685,686],{"class":62}," \n",[56,688,689,692,695,698],{"class":58,"line":456},[56,690,691],{"class":123},"      await",[56,693,694],{"class":62}," weatherService.",[56,696,697],{"class":66},"getWeather",[56,699,700],{"class":62},"(cityName),\n",[56,702,703],{"class":58,"line":472},[56,704,705],{"class":62},"  });\n",[56,707,708],{"class":58,"line":477},[56,709,203],{"class":62},[11,711,712,713,716,717,720],{},"في هذا المثال، نستخدم واجهة ",[25,714,715],{},"Resource API"," لجلب بيانات الطقس لمدينة معينة، حيث يتم تحديد المدينة باستخدام إشارة ",[32,718,719],{},"city"," التي يتم تحديثها حسب الحاجة.",[11,722,723,724,727],{},"عند تغيير اسم المدينة، يقوم ",[25,725,726],{},"Resource"," تلقائيًا بجلب بيانات الطقس الجديدة.",[11,729,730,731,734],{},"الخدمة ",[32,732,733],{},"weatherService"," مسؤولة عن جلب البيانات من مصدر خارجي، مثل API.",[11,736,737,738,740],{},"هذا الأسلوب يجعل عملية جلب البيانات وإدارتها أكثر سهولة، حيث يتولى ",[25,739,715],{}," إدارة الحالة مثل التحميل (loading) أو التعامل مع الأخطاء، مما يقلل من التعقيد البرمجي.",[11,742,743,744,158],{},"أيضا هذه الخاصية ما زالت قيد التطوير والمراجعة، ويمكنك الإطلاع علي معلومات أكثر ",[149,745,157],{"href":746,"rel":747,"target":156},"https:\u002F\u002Fangular.dev\u002Fguide\u002Fsignals\u002Fresource",[153,154,155],[21,749,751],{"id":750},"دعم-ضبط-وضعيات-التنقل-routing-mode",[25,752,753],{},"دعم ضبط وضعيات التنقل (Routing mode)",[11,755,756],{},"تم إضافة واجهة جديدة تُسمى ServerRoute، تتيح لك تحديد طريقة عرض كل مسار، سواء على الخادم، أو بشكل مسبق، أو على جانب العميل، كما في المثال التالي :",[47,758,760],{"className":49,"code":759,"language":51,"meta":52,"style":52},"export const serverRouteConfig: ServerRoute[] = [\n { path: '\u002Flogin', mode: RenderMode.Server },\n { path: '\u002Fdashboard', mode: RenderMode.Client },\n { path: '\u002F**', mode: RenderMode.Prerender },\n];\n",[32,761,762,787,798,808,818],{"__ignoreMap":52},[56,763,764,766,769,772,775,778,781,784],{"class":58,"line":59},[56,765,124],{"class":123},[56,767,768],{"class":123}," const",[56,770,771],{"class":103}," serverRouteConfig",[56,773,774],{"class":123},":",[56,776,777],{"class":66}," ServerRoute",[56,779,780],{"class":62},"[] ",[56,782,783],{"class":123},"=",[56,785,786],{"class":62}," [\n",[56,788,789,792,795],{"class":58,"line":73},[56,790,791],{"class":62}," { path: ",[56,793,794],{"class":79},"'\u002Flogin'",[56,796,797],{"class":62},", mode: RenderMode.Server },\n",[56,799,800,802,805],{"class":58,"line":86},[56,801,791],{"class":62},[56,803,804],{"class":79},"'\u002Fdashboard'",[56,806,807],{"class":62},", mode: RenderMode.Client },\n",[56,809,810,812,815],{"class":58,"line":97},[56,811,791],{"class":62},[56,813,814],{"class":79},"'\u002F**'",[56,816,817],{"class":62},", mode: RenderMode.Prerender },\n",[56,819,820],{"class":58,"line":114},[56,821,822],{"class":62},"];\n",[11,824,825,826,158],{},"هذه الخاصية أيضا ما زالت قيد التطوير والمراجعة، ويمكنك الإطلاع علي معلومات أكثر ",[149,827,157],{"href":828,"rel":829,"target":156},"https:\u002F\u002Fangular.dev\u002Fguide\u002Fhybrid-rendering#rendering-modes",[153,154,155],[21,831,833],{"id":832},"صياغة-المتغيرات-الجديدة-let",[25,834,835],{},"صياغة المتغيرات الجديدة @let",[11,837,838,839,842],{},"دعم صياغة جديدة للمتغيرات باسم ",[25,840,841],{},"@let","، حيث تم تقديمها في الإصدار 18.1 وأصبحت الآن مستقرة في الإصدار 19.",[11,844,845],{},"تساعد هذه الصياغة على تبسيط تعريف المتغيرات داخل القوالب (Templates) وإعادة استخدامها بسهولة لتخزين القيم والتعبيرات.",[47,847,849],{"className":177,"code":848,"language":179,"meta":52,"style":52},"@let userName = 'Jane Doe';\n\u003Ch1>Welcome, {{ userName }}\u003C\u002Fh1>\n\n\u003Cinput #userInput type=\"text\">\n@let greeting = 'Hello, ' + userInput.value;\n\u003Cp>{{ greeting }}\u003C\u002Fp>\n\n@let userData = userObservable$ | async;\n\u003Cdiv>User details: {{ userData.name }}\u003C\u002Fdiv>\n",[32,850,851,856,871,875,895,900,913,917,922],{"__ignoreMap":52},[56,852,853],{"class":58,"line":59},[56,854,855],{"class":62},"@let userName = 'Jane Doe';\n",[56,857,858,860,863,866,868],{"class":58,"line":73},[56,859,606],{"class":62},[56,861,862],{"class":194},"h1",[56,864,865],{"class":62},">Welcome, {{ userName }}\u003C\u002F",[56,867,862],{"class":194},[56,869,870],{"class":62},">\n",[56,872,873],{"class":58,"line":86},[56,874,373],{"emptyLinePlaceholder":372},[56,876,877,879,882,885,888,890,893],{"class":58,"line":97},[56,878,606],{"class":62},[56,880,881],{"class":194},"input",[56,883,884],{"class":66}," #userInput",[56,886,887],{"class":66}," type",[56,889,783],{"class":62},[56,891,892],{"class":79},"\"text\"",[56,894,870],{"class":62},[56,896,897],{"class":58,"line":114},[56,898,899],{"class":62},"@let greeting = 'Hello, ' + userInput.value;\n",[56,901,902,904,906,909,911],{"class":58,"line":120},[56,903,606],{"class":62},[56,905,11],{"class":194},[56,907,908],{"class":62},">{{ greeting }}\u003C\u002F",[56,910,11],{"class":194},[56,912,870],{"class":62},[56,914,915],{"class":58,"line":429},[56,916,373],{"emptyLinePlaceholder":372},[56,918,919],{"class":58,"line":434},[56,920,921],{"class":62},"@let userData = userObservable$ | async;\n",[56,923,924,926,929,932,934],{"class":58,"line":440},[56,925,606],{"class":62},[56,927,928],{"class":194},"div",[56,930,931],{"class":62},">User details: {{ userData.name }}\u003C\u002F",[56,933,928],{"class":194},[56,935,870],{"class":62},[11,937,938,939,941],{},"لكن لاحظ أن المتغيرات التي يتم تعريفها باستخدام ",[25,940,841],{}," تكون للقراءة فقط (Read-only)، ولا يمكن تعديل قيمتها بعد تعريفها، كما يقتصر نطاق استخدامها على القالب الحالي والفروع التابعة له.",[11,943,944,945],{},"للمزيد حول هذه الميزة ",[149,946,949],{"href":947,"rel":948,"target":156},"https:\u002F\u002Fangular.dev\u002Fguide\u002Ftemplates\u002Fvariables#local-template-variables-with-let",[153,154,155],"اضغط هنا",[21,951,953],{"id":952},"تحديثات-أخري",[25,954,955],{},"تحديثات أخري",[957,958,959,967,977],"ul",{},[960,961,962,963,966],"li",{},"تحسين خاصية ",[25,964,965],{},"HMR"," بحيث يتم تحديث التطبيق بشكل أكثر سلاسة في حالة إجراء تعديلات علي الكود، مثلا إن تم تعديل الاستايل في المحرر سيظهر التعديل لحظيا في الشاشة، مما يساهم في تقليل وقت التطوير ويوفر تجربة تطوير مستمرة دون انقطاع.",[960,968,969,972,973,976],{},[25,970,971],{},"تحسين أدوات الاختبار:"," دعم أفضل لإطار ",[25,974,975],{},"Jest"," مع تحسين أداء مشغل الاختبارات، مما يسهم في تعزيز جودة الكود وسهولة التحقق من موثوقيته أثناء التطوير.",[960,978,979,982],{},[25,980,981],{},"تعزيز الأمان:"," يستفيد Angular من ممارسات Google القوية في الأمان، مع تحديثات دورية لمعالجة الثغرات بسرعة.",[21,984,986],{"id":985},"تحديثات-angular-material",[25,987,988],{},"تحديثات Angular Material",[11,990,991],{},[234,992],{"alt":52,"src":993},"\u002Fimages\u002F678feb411a22a9426af87e4c.webp",[11,995,996,997],{},"تم تبسيط تجربة انشاء استايل جديد باستخدام الواجهه ",[25,998,999],{},"mat.theme",[47,1001,1005],{"className":1002,"code":1003,"language":1004,"meta":52,"style":52},"language-scss shiki shiki-themes github-dark","@use '@angular\u002Fmaterial' as mat;\n\nhtml {\n  @include mat.theme((\n    color: (\n      primary: mat.$violet-palette,\n      tertiary: mat.$orange-palette,\n      theme-type: light\n    ),\n    typography: Roboto,\n    density: 0\n  ));\n}\n","scss",[32,1006,1007,1024,1028,1034,1049,1057,1072,1086,1100,1105,1110,1118,1123],{"__ignoreMap":52},[56,1008,1009,1012,1015,1018,1021],{"class":58,"line":59},[56,1010,1011],{"class":123},"@use",[56,1013,1014],{"class":79}," '@angular\u002Fmaterial'",[56,1016,1017],{"class":123}," as",[56,1019,1020],{"class":597}," mat",[56,1022,1023],{"class":62},";\n",[56,1025,1026],{"class":58,"line":73},[56,1027,373],{"emptyLinePlaceholder":372},[56,1029,1030,1032],{"class":58,"line":86},[56,1031,179],{"class":194},[56,1033,592],{"class":62},[56,1035,1036,1039,1041,1043,1046],{"class":58,"line":97},[56,1037,1038],{"class":123},"  @include",[56,1040,1020],{"class":597},[56,1042,158],{"class":62},[56,1044,1045],{"class":66},"theme",[56,1047,1048],{"class":62},"((\n",[56,1050,1051,1054],{"class":58,"line":114},[56,1052,1053],{"class":103},"    color",[56,1055,1056],{"class":62},": (\n",[56,1058,1059,1062,1065,1067,1070],{"class":58,"line":120},[56,1060,1061],{"class":62},"      primary: ",[56,1063,1064],{"class":597},"mat",[56,1066,158],{"class":62},[56,1068,1069],{"class":597},"$violet-palette",[56,1071,83],{"class":62},[56,1073,1074,1077,1079,1081,1084],{"class":58,"line":429},[56,1075,1076],{"class":62},"      tertiary: ",[56,1078,1064],{"class":597},[56,1080,158],{"class":62},[56,1082,1083],{"class":597},"$orange-palette",[56,1085,83],{"class":62},[56,1087,1088,1091,1094,1097],{"class":58,"line":434},[56,1089,1090],{"class":62},"      theme",[56,1092,1093],{"class":103},"-",[56,1095,1096],{"class":62},"type: ",[56,1098,1099],{"class":103},"light\n",[56,1101,1102],{"class":58,"line":440},[56,1103,1104],{"class":62},"    ),\n",[56,1106,1107],{"class":58,"line":456},[56,1108,1109],{"class":62},"    typography: Roboto,\n",[56,1111,1112,1115],{"class":58,"line":472},[56,1113,1114],{"class":62},"    density: ",[56,1116,1117],{"class":103},"0\n",[56,1119,1120],{"class":58,"line":477},[56,1121,1122],{"class":62},"  ));\n",[56,1124,1125],{"class":58,"line":483},[56,1126,203],{"class":62},[11,1128,1129],{},"لن تحتاج أكثر من الكود السابق لضبط الحد الأدني من إعدادات الاستايل للتطبيق.",[11,1131,1132,1133,1136],{},"أيضا تم إضافة مزايا جديدة للمكونات تجعلها أكثر فاعلية، مثل دعم ",[25,1134,1135],{},"السحب والإفلات ثنائي الأبعاد","، الذي يسمح بتحريك العناصر أفقيًا وعموديًا.",[11,1138,1139],{},[234,1140],{"alt":52,"src":1141},"\u002Fimages\u002F678feb051a22a9426af87e3e.webp",[11,1143,1144,1145,1148],{},"كما تم اضافة مكون جديد ",[25,1146,1147],{},"اختيار الوقت (Time Picker)","، الذي طال انتظاره وتم طلبه أكثر من مرة.",[11,1150,1151],{},"وبشكل عام تم تحسين التوثيق الرسمي ليصبح أكثر وضوحًا وشمولًا، مع إضافة قسم (tab) جديد لكل مكون باسم (Styling) لتوضيح كيفية تخصيص الاستايل والأنماط لهذا المكون.",[21,1153,1155],{"id":1154},"التطويرات-والخطط-المستقبلية",[25,1156,1157],{},"التطويرات والخطط المستقبلية",[957,1159,1160,1167,1174,1185],{},[960,1161,1162,1163,1166],{},"يعمل فريق Angular على تطوير ميزة جديدة للنماذج تُسمى ",[25,1164,1165],{},"Signal Forms","، والتي تهدف إلى تحسين إدارة الحالة التفاعلية للنماذج، حيث يعتمد هذا الحل على استخدام الإشارات (Signals) لتلبية احتياجات المطورين بطريقة أسهل وأكثر كفاءة بناءً على ردود فعل المستخدمين.",[960,1168,1169,1170,1173],{},"لتحسين تجربة العمل مع المكونات المستقلة (Standalone Components)، يتم العمل على ميزة جديدة تُسمى ",[25,1171,1172],{},"Selectorless","، ستجعل هذه الميزة استخدام المكونات والموجهات (Directives) أسهل من خلال إزالة الحاجة إلى تعريف معرّفات (Selectors)، مما يتيح استيرادها واستخدامها مباشرة داخل القوالب، مع التنويه أن الميزة لا تزال في مراحل التخطيط المبكرة.",[960,1175,1176,1177,1180,1181,1184],{},"في مجال ",[25,1178,1179],{},"العرض من جانب الخادم (SSR)","، يعمل الفريق على تحسين الأداء من خلال استكشاف ميزة ",[25,1182,1183],{},"العرض المتدفق (Streamed Server-Side Rendering)"," لدعم التطبيقات التي لا تعتمد على المناطق (Zoneless)، بهدف تحسين سرعة التطبيقات ومرونتها.",[960,1186,1187,1188,1193,1194,1197,1198,243,1201,243,1203,1206],{},"مع ",[149,1189,1192],{"href":1190,"rel":1191,"target":156},"https:\u002F\u002Fgithub.com\u002Fkarma-runner\u002Fkarma?tab=readme-ov-file#karma-is-deprecated-and-is-not-accepting-new-features-or-general-bug-fixes",[153,154,155],"إيقاف دعم"," أداة الاختبار ",[25,1195,1196],{},"Karma","، يتم البحث عن بديل ليكون الخيار الافتراضي لتطبيقات Angular. حاليًا، يتم تقييم أدوات مثل ",[25,1199,1200],{},"Web Test Runner",[25,1202,975],{},[25,1204,1205],{},"Vitest"," لاختيار الأداة الأنسب ودمجها مع واجهة الأوامر (CLI).",[21,1208,1210],{"id":1209},"خاتمة",[25,1211,1209],{},[11,1213,1214],{},"الترقية إلى Angular 19 توفر مجموعة متنوعة من الميزات الجديدة التي يمكن أن تعزز بشكل كبير تطبيقاتنا.",[11,1216,1217],{},"من خلال استكشاف هذه التحسينات، يمكننا تحسين أداء مشاريعنا، وسهولة استخدامها، وقابليتها للصيانة.",[11,1219,1220],{},"إن أعجبك هذا النوع من المحتوي، أرجو أن تخبرني بذلك في التعليقات، وأرجو ألا تحرمني من ملاحظاتك ومقترحاتك لتطوير المدونة بشكل عام.",[11,1222,1223],{},"وفقنى الله وإياك إلى ما يحبه ويرضاه ،،",[1225,1226,1227],"style",{},"html pre.shiki code .s95oV, html code.shiki .s95oV{--shiki-default:#E1E4E8}html pre.shiki code .svObZ, html code.shiki .svObZ{--shiki-default:#B392F0}html pre.shiki code .sU2Wk, html code.shiki .sU2Wk{--shiki-default:#9ECBFF}html pre.shiki code .sDLfK, html code.shiki .sDLfK{--shiki-default:#79B8FF}html pre.shiki code .sAwPA, html code.shiki .sAwPA{--shiki-default:#6A737D}html pre.shiki code .snl16, html code.shiki .snl16{--shiki-default:#F97583}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html pre.shiki code .s4JwU, html code.shiki .s4JwU{--shiki-default:#85E89D}html pre.shiki code .s9osk, html code.shiki .s9osk{--shiki-default:#FFAB70}",{"title":52,"searchDepth":73,"depth":86,"links":1229},[1230,1231,1232,1233,1234,1235,1236,1237,1238,1239,1240],{"id":23,"depth":73,"text":27},{"id":161,"depth":73,"text":164},{"id":227,"depth":73,"text":230},{"id":317,"depth":73,"text":320},{"id":555,"depth":73,"text":558},{"id":750,"depth":73,"text":753},{"id":832,"depth":73,"text":835},{"id":952,"depth":73,"text":955},{"id":985,"depth":73,"text":988},{"id":1154,"depth":73,"text":1157},{"id":1209,"depth":73,"text":1209},"\u002Fimages\u002F678fe40d1a22a9426af87e16.webp","\u002Fimages\u002F678fe40d1a22a9426af87e16_thumb.webp","2025-01-21T18:14:02.387Z","2025-01-21T19:25:28.660Z","استعراض لأبرز التحديثات في الإصدار الجديد من Angular، مع تسليط الضوء على أبرز الجوانب التي يمكنك الاستفادة منها في تحسين تطبيقاتك الحالية والمستقبلية - بإذن الله.","md",{},"\u002Farticles\u002F678fe3ea1a22a9426af87e0b",{"title":5,"description":1245},"articles\u002F678fe3ea1a22a9426af87e0b",[1252],{"id":1253,"label":1254},"65ae26201d50740dab36fdb3","اطار Angular","2025-01-21T19:25:28.854Z","n4HYSmTTpXQFQMHv8zH1u4IQDWaeEM5fuh34uIBh0D0",1788209571767]