البحث في الموقع
المحتوى عن 'مجالات'.
-
يقسِّم كثير من الناس وقتهم في العمل على الإنترنت بين العديد من المهام، ما بين التسويق في الصباح، صناعة المحتوى في الظهيرة، وكتابة مراجعات زائفة في المساء، لكنك لن تجد مستقلًا حقيقيًا يفكر في تقسيم وقته بين مجالات مختلفة، أليس كذلك؟ ورغم أن الطريق ﻻ زال طويلًا أمامي كي أصير خبيرًا في أي من المجالين اللذين اخترت العمل فيهما، وهما الكتابة وتطوير الويب، إﻻ أني استطعت تحقيق توازن بين العمل الحر في كليهما، رغم أنهما عالَميان مختلفان. ولم يكن اختياري لهذين المجالين بسبب المال، بل كان قرارًا شخصيًا بمطاردة المجاليْن اللذيْن يرضياني عن طريق أسلوب العمل الوحيد الذي أعرفه: مباشرة من المنزل. لذا تحمّل معي رجاءً إن كنتَ مهتمّا بتجربة الأمر بينما أشرح كيف نجح الأمر في حالتي، وكيف يمكن أن ينجح في حالتك أيضًا، والأسباب التي قد تحول دون ذلك. لماذا نجحت في العمل الحر في عدة مجالات (ولماذا قد ينجح معك أيضا) إنني أعمل هذه الأيام ككاتب ومطور ويب مهووس بووردبريس، ولي بضع سنين على تلك الحال. غير أن بداياتي في العمل كمستقل أخذتني إلى طرق ومسالك ﻻ زلت أرتعد كلما تذكَّرْتُها، أذكر منها خصيصًا كتابتي لبعض شركات صناعة المحتوى، تفريغ ملفات صوتية مبهمة تبدو كأنها تستعصي على من يحاول فك شفرتها من أجل أجر بخس، وملء استبيانات ﻻ نهاية لها. إن هذا بالكاد عمل مناسب، لكن ﻻ يغرّنك ذلك، فبضعة دولارات تستطيع فعل الكثير في دولة من العالم الثالث، كما أني ﻻ زلت أحتفظ بوظيفة عادية إلى حين تنتظم هذه الأعمال العشوائية ويتحول أصحابها إلى عملاء مستقرين ودائمين. وبعيدًا عن البغض الظاهر تجاه المشاريع واﻷعمال المستغِلَّة، فإن خوضي للعديد من المشاريع والوظائف عبر الإنترنت منحتني ميزة واحدة واضحة، فقد اكتشفت أن لدي ولعًا بالكتابة. لذا قررت أن أتابع العمل فيها كهواية بينما أبني مسيرة عمل مستقرة كمطور ويب. وقد آتت خلفيتي الانتقائية اُُكُلها مع الوقت، فقد منحتني خلفيتي في تطوير الويب أفضلية حين كنت أتقدم لوظائف كتابة تتعلق باﻷمور التقنية، فإن تطوير الويب ﻻ تقتصر فائدته على معرفتك بالأدوات والعمليات التي تكون بصددها فحسب، بل يعلمك أيضًا أن تفضِّل جوجل على أي شيء آخر. وبالطبع فإن مهارات البحث تنفعك كثيرًا حين تحتاج أن تكتب عن موضوع ما بشكل تعليمي أو ليكون مرجعًا. وبشكل ما، فإن ما بدأ كتشكيلة غريبة من مجالين مختلفين سعيت فيهما لمجرد تفضيلاتي الشخصية، تحول إلى خطوة جيدة في مسيرتي المهنية. وقد نفعتني قدرتي على التعبير عن نفسي بوضوح حين كنت أتعامل مع العملاء -رغم أني ﻻ زلت أطوِّر من نفسي كي أتعلم الإيجاز والاختصار-، كما فتحت لي مهاراتي في تطوير الويب مجالات عديدة في عالم الكتابة. انتبه!، ﻻ أريدك أن تظن أني أدعي التميز أو أني موهوب بشكل خاص، بل إني أحسَب أن العديد منكم لديهم مهارات قيِّمة يمكن أن تعمل معًا بشكل رائع، وتفتح أبواب رزق لكم من حيث لم تحتسبوا. إليكم بعض اﻷمثلة على ذلك: إن كنت تهوى التصوير الفوتوجرافي، فيمكن أن توظف تلك الهواية في أعمال التصميم الجرافيكي Graphic Design. إذا كنت تساعد العملاء على تطوير خططهم التسويقية عبر الإنترنت، فإن وجود خلفية عن التصميم المرئي تمكنك من إرفاق شروح Infographic تفصيلية مع عروضك. إذا كنت تستمتع بالكتابة، فذلك شيء رائع، حيث أن الكتابة يمكن أن تُوّظَّف في خدمة أي مجال تقريبًا. إذا كنت تشعر أنني لم أثبت وجهة نظري بعد، فاسمح لي أن أكمل لك الأمر بكشف فائدتين جديدتين للعمل الحر في عدة مجالات: إن تقسيم وقتك بين منطقتين يزودك بطريقة ﻹراحة نفسك من الإجهاد الذي قد ينتج عن كليهما، فالكتابة تفعل الأعاجيب معي بعد الجلسات الطويلة لمعالجة الأعطال، كما تزودني البرمجة بالقواعد التي أحتاجها لشطف وإزالة أي أحلام يقظة مبالغ فيها نتيجة العمل في الكتابة. كونك أسست نفسك جيدًا في أحد المجالين يجعل من السهل عليك القفز في المجال الآخر دون قلق بشأن المآزق المعتادة التي يجدها المرء حين يبدأ العمل كمستقل في مجال جديد (مثل قلة العملاء في البداية، فقدان مستوى الأجر المعتاد، إلخ). لماذا قد "ﻻ" ينجح معك العمل الحر في أكثر من مجال واﻵن، بعد أن أقنعتك (آمل هذا) أنك قد تنجح في العمل الحر كمستقل في أكثر من مجال، دعني ألعب دور محامي الشيطان ﻷريك اﻷسباب التي قد تجعل من هذا الأسلوب فكرة سيئة ﻻ يجب عليك العمل بها أو تنفيذها، أو بشكل أدق، ﻷريك الحالات التي يجب أن تتجنب العمل فيها في أكثر من مجال. بادئ ذي بدء، فإن تقسيم وقتك بين مجالين أو أكثر يعني أن لديك مزيدًا من العمل على عاتقك، وهذا يعني وقتًا أكثر، كما أن تسلق السلم في كلا المجالين يتطلب استثمارًا أكثر في تطوير مهاراتك. وبصراحة، إن كنت ﻻ تملك وقتًا كافيًا، فإن مغامرتك في مجال جديد لن تنتهي على خير، سواء لك أو لعملائك. إن وجود وقت فراغ أقل يترجَم إلى مستويات أعلى من الإجهاد، فإذا كنت تحسب أن تدبير معيشتك كمستقل بجانب التعامل مع توقعات العملاء أمر صعب، فلتضاعف تلك الصعوبة بمقدار الضعف على الأقل إن كنت تعمل في مجالين فقط. أضف إلى هذا أنك إن لم تستطع التحكم في إجهادك بشكل سليم، فإن جودة عملك سوف تتهاوى بلا ريب. وفي النهاية، فإن من المستحيل أن تحقق توازنًا بين أكثر من مجال إﻻ إذا كنت متأكدًا من خطواتك من الأساس، تذكر أيامك الأولى في العمل الحر ثم اسأل نفسك بصدق: هل كنت لتنجح إن كنت مضطرًا إلى الموازنة بين مجموعتين مختلفتين من القواعد والتوقعات، في مجالين مختلفين، في وقت واحد؟ إنني أتوقع أن تكون الإجابة هي "ﻻ"، اللهم إﻻ إن كنت روبوتًا!. والحقيقة أن مبدأ العمل في مجالات مختلفة في نفس الوقت ينجح فقط إذا كانت لديك بعض المرونة في حياتك المهنية، أو إن كنت تنوي اعتماد بعض المرونة. أما إن كنت ﻻ زلت في بداياتك في العمل الحر كمستقل، فربما تود أن تجرب التواصل مع عملائك بلغة لا يفهمونها ، ﻷن نتائج تجربة هذه الطريقة لن تقل كارثية عن تجربة العمل في أكثر من مجال إن كنت مبتدئًا!. الخلاصة يعقد كثير من الناس عزمهم على تركيز جهودهم في العمل على مجال واحد لزيادة فرصهم في النجاح، وهذا قرار منطقي بالمناسبة، لكن ﻻ زال بوسعك رغم هذا أن تحقق نجاحًا أفضل بتقسيم جهدك إن أخذت بما شرحته في مقالي هاهنا. والآن، دعنا نراجع ما غطيناه في هذا المقال: فوائد العمل الحر في عدة مجالات يمكنك من البحث في اهتمامات جديدة بصفة مهنية احترافية. يزودك بطريقة تتخلص بها من الإجهاد الناتج عن أحد تلك المجالات. تؤهلك مهاراتك المتنوعة لمزيد من العملاء المحتملين. عيوب العمل الحر في عدة مجالات تستهلك وقتًا أكبر من الذي تستغرقه في التركيز على مجال واحد. ستجد نفسك مشتتًا في عدة اتجاهات. سيكون من الصعب أن توازن بين العمل في مجالين إﻻ إن كان مستواك جيدًا بالفعل في أحدهما. هل لديك أية أسئلة عن اختيار مجال جديد للعمل به كمستقل، أو هل لديك تجربة في هذا الأمر تود مشاركتها معنا؟ دعنا نعرف منك في التعليقات. ترجمة -وبتصرف- للمقال Is It Possible to Freelance Across Multiple Fields لصاحبه Alexander Cordova. حقوق الصورة البارزة: Designed by Freepik.
-
ما الذي تعنيه كلمة "مجال" برأيك؟ قد تبدو من اسمها بأنّها تشير إلى جزءٍ من شيفرة التّطبيق، ربّما تم عملها لنتجنّب استخدام المجال العام الذي يسبّب العديد من المشاكل. يبدو أنّ الأمر بسيط، وإنّه لمن الحكمة أن يقوم إطار العمل بتطبيق شيءٍ كهذا، ربّما ليس علينا التّفكير في أمر المجالات أكثر من ذلك، هل يمكننا الانتقال للفصل التالي؟ ليس بهذه السّرعة، لن يكون هذا الفصل طويلًا ولكنه سيغطي أمرين شديدي الأهمّيّة: وراثة المجالات، وهرميّة المجالات، فقد يحوي تطبيق Angular نموذجيًّا على العشرات، المئات وربّما الآلاف من المجالات. قبل أن نبدأ، لنقم بإعداد البيئة لتُلائم أمثلة هذا الفصل. التهيئةفي فصل المبادئ، تعلّمنا كيف نقوم بإضافة التّوجيه ng-app إلى العنصر الذي نرغب بأن تقوم Angular بمعالجته. <body ng-app="app"> <!-- الأمثلة هنا --> </body>الوسيط الذي نمرره إلى التّوجيه ng-app هو اسم الوحدة التي تشكل جذر التطبيق الحالي (في المثال قمنا باستخدام الاسم app على سبيل الاصطلاح). سنقوم بتغطية الوحدات بعمق في فصل لاحق. أما الآن فاعتبر السّطور التّالية مجرّد شيفرات اصطلاحية يمكنك نسخها دون فهم محتواها. angular.module('app', []); angular.module('app').config(['$controllerProvider', function($controllerProvider) { $controllerProvider.allowGlobals(); }]);والآن بعد كتابة تلك الشّيفرات الخارجة عن الدّرس، يمكننا الدخول في الموضوع. scope$في الفصل الماضي، المتحكمات، تعلّمنا كيفيّة تحضير النّموذج عن طريق ربط العناصر (الخصائص properties) إلى المرجع scope$. لنقم بتكرار التمرين ثانيةّ. function NameController($scope) { $scope.name = "First"; }باستخدام التّوجيه ng-controller يمكننا استدعاء تابع التّحكم المكتوب أعلاه، وذلك ضمن سياق أحد عناصر المستند، وعندها ستكون أيّ بيانات قمنا بإسنادها للمجال متاحةً للاستخدام داخل العنصر. <p ng-controller="NameController"> {{name}} </p>الناتج Firstعناصر المستند التي تقع خارج العنصر الذي قمنا باستدعاء المتحكّم NameController فيه، لن تكون قادرةً على الوصول إلى العناصر المرتبطة بالمتحكّم، لنجرّب ذلك. <div> <p> Outside the scope: {{name}} </p> <div ng-controller="NameController"> <p> Inside the scope: {{name}} </p> </div> </div>الناتج Outside the scope: Inside the scope: Firstوهذا المثال يوضّح ارتباط عمل المتحكّم والمجال معًا، والآن لننظر إلى الحالة المعاكسة، تطبيق Angular بمجال واحد. rootScope$تحاول Angular جاهدةً أن تتأكد من ابتعادنا عن المشاكل أثناء استخدام المجالات، لذا تقوم بإنشاء مجالٍ جديد لكلّ متحكّم. يتمّ بناء المجالات وفق بنيةٍ هرميّة، ويتربّع في جذر هرم المجالات في كلّ تطبيقات Angular مجالٌ أبٌ وحيدٌ لجميع المجالات، يمكننا الوصول إلى هذا الجذر باستخدام الوسيط ذو الاسم المخصص rootScope$ داخل المتحكّم، واستخدامه بدلًا من المرجع المعتاد (والمستحسن) scope$. function RootNameController($rootScope) { $rootScope.name = "First"; }الشّيفرة واضحة وليس فيها صعوبة، وهي تعمل بشكل طبيعي. <p ng-controller="RootNameController"> {{name}} </p>الناتج Firstولكنّ المشاكل تبدأ بالظّهور عندما نحاول الوصول إلى عنصر له الاسم نفسه من متحكّم آخر. function SecondRootNameController($rootScope) { $rootScope.name = "Second"; }هذا لا يبشّر بالخير، فالمرجع rootScope$ وحيد (singleton) داخل التّطبيق، ولا يمكن أن يكون هناك سوى عنصر واحد له الاسم name. <p ng-controller="RootNameController"> {{name}} </p> <p ng-controller="SecondRootNameController"> {{name}} </p>الناتج Second Secondمن الواضح أنّ المتحكّم SecondRootNameController قد استبدل القيمة التي أسندها RootNameController للعنصر name. حسنًا، هذه هي مشكلة المتغيرات العامة، أليس كذلك؟ العزلتقدم Angular لنا بيئة آمنة عن طريق إنشاء مجالٍ خاصّ بكلّ متحكّم، لنقم بإعادة كتابة المتحكّمات السّابقة لتقوم بتهيئة النّموذج تهيئةً صحيحة، باستخدام المرجع scope$ بدلًا من rootScope$، وحاول مقارنة ذلك مع المثال السّابق الذي استخدمنا فيه rootScope$ لتعرف سبب إنشاء مجال لكلّ متحكّم، سنستخدم المتحكّمين التاليين: function SecondNameController($scope) { $scope.name = "Second"; }<p ng-controller="NameController"> {{name}} </p> <p ng-controller="SecondNameController"> {{name}} </p>الناتج First Secondأظهر المثال المخرجات الصحيحة، القيمة الصحيحة للعنصر name لكلا المتحكّمين. هذا العزل هو النّتيجة التي نحصل عليها عندما لا يكون أيٌّ من المتحكّمين ابنًا للآخر، أيّ أننا لم نقم بتعريف أحد المتحكّمين داخل عنصر في المستند محتوًى داخل متحكّمٍ آخر. ما الذي سيحدث لو قمنا بجعلهم متداخلين بدلًا من ذلك؟ المجالات المتداخلةبتعديلٍ صغيرٍ على المثال السابق، سنقوم بتحريك SecondNameController إلى عنصرٍ ابن للعنصر div الذي يقوم بتحميل المتحكّم NameController، وهذه الحالة هي ما يسمّى بالمجالات المتداخلة (nested). <div ng-controller="NameController"> <p> {{name}} </p> <p ng-controller="SecondNameController"> {{name}} </p> </div>الناتج First Secondالأمور تسير على ما يُرام، ولا يزال العنصر name معزولًا في كلا المجالين، ماذا لو قمتَ بعكس ترتيب العنصرين p في المثال السابق؟ هيا قم بتجربة ذلك، يُفترض بأنك سترى أنّ العنصرين name قد انعكس ترتيبهما. في الحقيقة، لا يعني ذلك بأنّ المجالين معزولين، فـAngular تقوم بتنظيم المتحكّمات في بنية هرميّة بالاعتماد على موضع المتحكّم في بنية المستند، والمتحكّم الابن يرث عناصر وخصائص أبيه. يرجع السبب في عدم حدوث تغيير في قيمة العنصر name في المثال السابق، إلى خاصّيّة التظليل، حيث يقوم العنصر name في الابن بتظليل قيمة العنصر name في الأب. لنجرّب الحصول على دليلٍ على هذا السلوك عن طريق تغيير اسم العنصر في المتحكّم الابن. function ChildController($scope) { $scope.childName = "Child"; }سنحاول إخراج قيمتي العنصرين في كلا المجالين، الأب والابن. <div ng-controller="NameController"> <p> {{name}} and {{childName}} </p> <p ng-controller="ChildController"> {{name}} and {{childName}} </p> </div>الناتج First and First and Childمن الواضح أنّ المتحكّم الأب NameController لا يملك صلاحيّةً للوصول إلى عناصر المتحكّم الابن، بينما يمكن للمتحكّم الابن ChildController أن يصل إلى عناصره وعناصر أبيه. بما أنّ العنصر name هو عنصر موروث من الأب، لا بدّ من أنّ التغيير على قيمته في مجال المتحكّم الابن سيؤدّي إلى تغيير قيمته في مجال الأب. سنضيف خانة إدخال ونربطها بالعنصر name. <div ng-controller="NameController"> <p> {{name}} </p> <p ng-controller="ChildController"> {{name}} </p> <input type='text' ng-model='name'> </div>إذا حاولت تعديل قيمة العنصر name في المثال السابق، ستجد أنّه يعمل كما هو متوقّع، فقيمة العنصر name تتغيّر في كلا المجالين، ولكن لاحظ بأنّنا نقوم بالتّغيير ضمن مجال الأب فقط. الوراثةقد ترغب أيضًا بتغيير قيمة العنصر name أيضًا في مجال الابن، ربّما تظنّ بأنّ هذا التغيير يجب أن ينعكس أيضًا على المتغير name في مجال الأب، لنجرّب ذلك، سنقوم بإضافة خانة إدخال لتسمح لنا بتعديل العنصر name في مجال الابن أيضًا. في العرض الخاصّ بالمثال، قم بالخطوات التالية بنفس الترتيب الذي سأذكره لك:أوّلًا، غيّر القيمة في خانة الإدخال العليا، ستلاحظ أنّ جميع القيم المرتبطة بالعنصر name قد تمّ تحديثها.ثانيًا، غيّر القيمة في خانة الإدخال السّفلى. <div ng-controller="NameController"> <p> name: {{name}} <br> <input type='text' ng-model='name'> </p> <p ng-controller="ChildController"> name: {{name}} <br> <input type='text' ng-model='name'> </p> </div>هل فاجَأَتك النّتيجة؟ تستخدم Angular طريقة JavaScript في وراثة الهيكل الخارجي (prototypal inheritance) هذا جيّدٌ إن كنت متمرّسًا فيها، فليس عليك تعلّم أيّ شيءٍ جديدٍ هنا، ولكنّه سيّءٌ لمن لم يواجه هذا النّوع من الوراثة من قبل، ففهمه ليس أمرًا بديهيًّا. تقول القاعدة: “إنّ تغيير قيمة عنصر ما في كائن في JavaScript، يؤدّي إلى إنشاء هذا العنصر في الكائن”، وهذه القاعدة البسيطة تشكّل مشكلةً أثناء التّعامل مع العناصر الموروثة التي تكون مظلّلة بالعنصر الخاص بالكائن الابن. حدث الأمر كالتّالي: في البداية لم يكن هناك أيّ عنصر اسمه name داخل الابن، ولكن عندما قمنا بتعديل النّصّ في خانة الإدخال السّفلى قامت Angular بإسناد النّص إلى العنصر name في الابن حيث تمّ إنشاء هذا العنصر في الابن، وعند حدوث ذلك، قام هذا العنصر بتظليل العنصر name في الأب، ومن ثمّ لم يعُد بإمكاننا الوصول إليه من الابن. كيف يمكننا التّعامل مع هذا الأمر في Angular، بحيث نتمكّن من تعديل بيانات النّموذج في مجالٍ موروث؟ لن يكون ذلك صعبًا، سيكون علينا فقط نقل العنصر name إلى داخل كائنٍ آخر. function InfoController($scope) { $scope.info = {name: "First"}; }function ChildInfoController($scope) { $scope.info.childName = "Child"; }<div ng-controller="InfoController"> <p> {{info.name}} and {{info.childName}} <br> <input type='text' ng-model='info.name'> </p> <p ng-controller="ChildInfoController"> {{info.name}} and {{info.childName}} <br> <input type='text' ng-model='info.name'> </p> </div>لاحظ أن ChildInfoController يعتمد على أبيه في إنشاء الكائن info، ما الذي سيحدث لو قمنا بتعديل شيفرة المتحكّم ChildInfoController واستبدلنا جسم التابع بالعبارة: scope.info = {childName: "Second$"};جرّب ذلك، سترى بأننا عدنا إلى إنشاء عنصرٍ جديد في الابن، مع تأثير التظليل الذي رأيناه سابقًا. scope.$watchتتعامل Angular أثناء عمليات الربط ثنائيّ الاتجاه مع العناصر في المجال بالطريقة التالية: عندما تستخدم خانة الدّخل المرتبطة للقيام بأيّ تغيير، يتمّ تحديث واجهة المستخدم في كلّ مكان، وهذا يختلف عن “الخصائص المحسوبة”(computed properties) وهي البيانات المأخوذة من مجال بيانات آخر. في المثال التالي، العنصر sum هو خصيصة محسوبة. function SumController($scope) { $scope.values = [1,2]; $scope.newValue = 1; $scope.add = function() { $scope.values.push(parseInt($scope.newValue)); }; // Broken -- doesn't trigger UI update $scope.sum = $scope.values.reduce(function(a, b) { return a + b; }); }يتم حساب قيمة العنصر sum فعليًّا عن طريق عملية بسيطة تستخدم التابع reduce في العبارة الأخيرة في المتحكّم SumController. في القالب الخاص بهذا المثال، سنستخدم أداة الدّخل select للسّماح للمستخدم باختيار الرّقم (2،1 أو 3) لإضافته إلى نهاية المصفوفة values.(كنقطة جانبيّة: لاحظ أنّ المتحكّم يعطي قيمةً ابتدائيّة للمتغيّر newValue, ولو لم نقم بذلك لكانت Angular ستضيف الاختيار الفارغ للقائمة في العنصر select، وذلك لتجنّب القيمة العشوائيّة التي يخزّنها newValue للخيار الأوّل المولّد عن طريق التّوجيه ng-options. هذا السلوك لا علاقة له بالمجالات ولكنّ العلم به أمرٌ مفيد.) <p ng-controller="SumController"> <select ng-model="newValue" ng-options="n for n in [1,2,3]"></select> <input type="button" value="Add" ng-click="add()"> The sum of {{values}} is {{sum}}. </p>عند النقر على Add ستتغيّر القيمة المعروضة لـsum، ولكن للأسف، الشّيفرة الخاصة بالمتحكّم تحتوي على أخطاء، ولن يعمل المتحكّم كما توقّعنا. لنقم الآن بتصحيح الخطأ، وذلك بنقل العبارة التي تقوم بالحساب الحقيقي للقيمة sum إلى تابع استدعاءٍ خلفيّ (callback). وعندما سنمرر هذا التابع كوسيط إلى scope.$watch$ مع وسيط آخر يمثّل عبارة المتابعة (في هذه الحالة هو اسم العنصر الذي يتم حساب sum منه)، سيؤدّي ذلك إلى جعل sum يتمّ إعادة حسابها كلّما تغيّر values. function SumController($scope) { $scope.values = [1,2]; $scope.newValue = 1; $scope.add = function() { $scope.values.push(parseInt($scope.newValue)); }; $scope.$watch('values', function () { $scope.sum = $scope.values.reduce(function(a, b) { return a + b; }); }, true); }والآن ستتغيّر قيمة العنصر sum ديناميكيًّا عند إضافة العناصر للمصفوفة. scope.$applyجميع التّوجيهات المدمجة في Angular والخاصة بعمليّة الربط ثنائيّ الاتجاه كاملة المزايا، ولكنّك قد تجد من فترة إلى أخرى سلوكًا تحتاج إلى إضافته. مثلًا، ماذا لو أردنا أن يقوم المستخدم بمسح الحالتين الحالة الحاليّة لخانة الدخل النّصّيّة و الحالة المرتبطة بها وذلك عندما يضغط زرّ esc؟ كيف يمكننا كتابة شيفرة التّعامل مع هذا الحدث؟ <div ng-controller="EscapeController"> <input type="text" ng-model="message"> is bound to "<strong ng-bind="message"></strong>". Press <code>esc</code> to clear it! </div>يجب علينا أوّلًا أن نصرّح عن المتغيّر ذو الاسم المخصّص element$ وتمريره كوسيط للمتحكّم، وذلك للسّماح لـAngular بحقن مرجعٍ في العنصر المرتبط بالمتحكّم. يمكننا استخدام التابع bind لتسجيل استدعاء خلفيّ لحدث keyup الذي يختبر ضغط الزّرّ esc، وداخل تابع الاستدعاء الخلفيّ هذا، سنقوم بتحديث عنصر المجال. قم بتجربة المثال التالي، اكتب شيئًا ثم اضغط esc. function EscapeController($scope, $element) { $scope.message = ''; $element.bind('keyup', function (event) { if (event.keyCode === 27) { // esc key // Broken -- doesn't trigger UI update $scope.message = ''; } }); }ليس بعد، بما أنّنا نتعامل مباشرةً (تقريبًا) مع عناصر المستند، سنحتاج إلى إخبار Angular عندما نريد أن تقوم بإعادة رسم العرض. نقوم بذلك عن طريق تغليف التّغييرات التي نقوم بها بتابع استدعاءٍ خلفيّ نمرّره إلى scope.$apply$. function EscapeController($scope, $element) { $scope.message = ''; $element.bind('keyup', function (event) { if (event.keyCode === 27) { // esc key $scope.$apply(function() { $scope.message = ''; }); } }); }جرّبها الآن، بعد أن أخبرنا Angular بما نريد، سيعمل كلّ شيء كما يجب. خلاصةإن حاولت تطبيق مفاهيم نموذج-عرض-متحكم (Model-view-controller (MVC على Angular، ستكون المجالات لغزًا بالنّسبة لك، قد تظنّ بأنّ الأمر بسيط، وأنّ المجالات هي جزءٌ من طبقة النّموذج، ولكن في Angular لا يكون الكائن نموذجًا حتّى يكون قابلًا للوصول إليه كعنصرٍ في المجال. ولكنّ القصّة تصبح أكثر إثارةً عندما ترى طريقة ارتباط المجالات بالمستند عن طريق المتحكّمات والتّوجيهات. بوضع سؤالنا الأكاديميّ جانبًا، فإن المجالات بديهيّةٌ وسهلة الاستخدام كما بيّنت أمثلة هذا الفصل. ترجمة وبتصرّف للفصل الرابع من كتاب: Angular Basics لصاحبه: Chris Smith.