دوره آموزش AngularJS – کنترل‌گرها (کنترلر AngularJS)

0006-learn-angularjs-course-beginner-controllers-featured-image

دوره آموزش AngularJS – کنترل‌گرها (کنترلر AngularJS)

در بخش قبلی این دوره آموزشی، مبانی، از شما خواستم تا AngularJS را به چشم یک فریمورک جاوااسکریپت نگاه نکنید. چرا؟ چون AngularJS قبل از آنکه یک فریمورک جاوااسکریپت باشد، آمده است تا به HTML قابلیت‌های جدید اضافه کند. ولی، داستان AngularJS در همین‌جا به پایان نمی‌رسد و بخش مهمی از هر اپلیکیشنی که با انگولار نوشته شده باشد را، Javascrript تشکیل می‌دهد. اگر در طی بخش مبانی از خود می‌پرسیدید، پس کی به کد زدن واقعی می‌رسیم، این بخش مخصوص شماست. الان وقت آن است که جاوااسکریپت بنویسیم.

عمومی‌ترین راه برای تقویت‌کردن لایه‌ی نمایش (View Layer) اپلیکیشن انگولار‌جی‌اس با کمک Javascript، استفاده از کنترل‌گر (Controller) است. ساده‌ترین راه نوشتن یک کنترل‌گر نوشتن آن با روش آشنای نوشتن یک تابع سازنده (Constructor Function) است.

تابع سازنده، در جاوااسکریپت به معنی معرفی یک تابع است که در آن از this برای معرفی خصوصیات و متد‌ها استفاده می‌شود و در نهایت با استفاده از new یک شیء از روی آن ساخته می‌شود.

برای فهم دقیق آنچیزی که قرار است اتفاق بیفتد، بیایید با یک کنترل‌گر خیلی ساده شروع کنیم. یک Controller که هیچ کاری انجام نمی‌دهد.

function EmptyController()
{
};
view raw empty-controller.js hosted with ❤ by GitHub

لازم به ذکر است که باید فایل فریمورک AngularJS را همچون مثال بخش قبل،مبانی، در صفحه وارد کنید.

<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.4.8/angular.min.js"></script>

به هیچ وجه فایل AngularJS را در قسمت پایین صفحه HTML، یعنی قبل از تگ </body> قرار ندهید. چون AngularJS میبایست در سریعترین زمان ممکن لود شود و کنترل صفحه را در دست بگیرد. با قرار دادن آن در انتهای سند HTML بارگذاری آنرا به زمانی که کل CSSهای سند و بطور کلی هر‌آنچه که قبل از آن آمده است موکول می‌کنید.

حالا می‌بایست یک ماژول اپلیکشن بسازیم. در بخش مبانی گفتیم که با نوشتن رهنمود (Directive) با نام ng-app به AngularJS می‌گوییم که این المان با کلیه‌ی فرزندانش اپلیکیشن ما را تشکیل می‌دهند. حالا به مثال زیر توجه کنید.

<body ng-app="app">
<!-- Other examples to be inserted here. -->
</body>
view raw index.html hosted with ❤ by GitHub

بنظر می‌رسد عبارتی نسبت به مثال‌های قبلی در بخش مبانی اضافه شده است. بنظرتان این عبارت اضافه شده چه کاربردی دارد؟ در ادامه به آن خواهیم پرداخت.

در این بخش، ما برای تعریف کنترل‌گرها از توابع سازنده‌ای که در حوزه‌ی سراسری (Global Scope) تعریف شده‌اند استفاده می‌کنیم. البته این تنها روش موجود برای تعریفشان نیست. اما در این بخش ما این روش را برگزیده‌ایم! تا نسخه‌ی ۱٫۳ اینگونه تعریف کنترل‌گرها در حوزه‌ی سراسری بصورت پیش‌فرض پشتیبانی می‌شد، اما از آن نسخه به بعد، برای استفاده از توابع سازنده در حوزه‌ی سراسری بعنوان Controller می‌بایست انگولار را پیکر‌بندی (Configure) کنیم. و برای پیکر‌بندی نیز نیاز است تا یک ماژول اپلیکیشن با نام بسازیم. برای همین نام app را به رهنمود ng-app اضافه نمودیم تا بتوانیم آنرا پیکربندی کنیم. توضیحات استفاده از angular.module در بخش ماژول‌ها (Modules)، تزریق وابستگی‌ها (Dependency Injection) و سرویس‌ها (Services) داده خواهد شد. اما تا آن زمان، قطعه کد پایین را بعنوان یک کد ضروری برای راه‌اندازی AngularJS در نظر بگیرید.

angular.module('app', []);
angular.module('app').config(['$controllerProvider', function ($controllerProvider)
{
$controllerProvider.allowGlobals();
}]);
view raw module.js hosted with ❤ by GitHub

حالا که فاز پیکر‌بندی را بخوبی پشت سر گذاشتیم، بهتر است کنترل‌گر noop خود را امتحان کنیم.

رهنمود ng-controller

همانند همیشه، راه اینکار استفاده از یک رهنمود است. رهنمود ng-controller، تابعی را که با نامش به او داده ایم را پیدا کرده و فرا‌‌می‌خواند.

<p ng-controller="EmptyController">
</p>


همانطور که انتظار داشتیم، این کنترل‌گر هیچ‌کاری انجام نمی‌دهد. و حالا این کنترل‌گر چیست و چگونه می توان از آن استفاده کرد.

ایجاد مدل

در بخش مرور مفهومی(Conceptual Overview) موجود در مستندات اصلی AngularJS، کار اصلی کنترل‌گر را “قرار دادن متغییر‌ها و قابلیت‌ها در اختیار عبارات و رهنمود‌ها” بیان نموده است. بخش قابلیت‌ها (Functionality) به توابع callback اشاره دارد. کمی بعد به این بخش خواهیم پرداخت. اما الان به بخش متغییر‌ها، مقدار‌دهی اولیه آنها و آماده سازی مدل می‌پردازیم.

این نکته که، یک مدل انگولار (Angular Model) در حقیقت جاوااسکریپت معمولی است که از طریق حوزه‌ی یک عبارت قابل دسترسی است، آماده سازی مدل را مثل یک لیوان آب خوردن می‌کند! جاوااسکریپت معمولی؟مطمعنا. به راحتی می‌توانیم کد را به روشی که همواره در جاوااسکریپت استفاده کردیم، بنویسیم. بیایید یک خاصیت ساده از نوع رشته به کنترل‌گر noopمان اضافه کنیم.

function MessageController()
{
this.message = "This is a model.";
}

ساده بود، نه؟ آیا کار ما تمام شده است؟ آیا با کد مثال قبل یک مدل ساخته ایم؟ بلی؟ خیر؟

جواب “تقریبا” است. ما می‌توانیم به خاصیت message از طریق حوزه‌ی تخصی یافته به لایه‌ی نمایش دسترسی پیدا کنیم، و در آنجاست که تبدیل به یک مدل می‌شود. یک راه برای انجام این‌کار این است که کل کنترل‌گر را بعنوان یک خاصیت به حوزه بدهیم. شاید به نظر مشکل بنظر برسد، اما اگر نحوه‌ی نوشتنش را بدانید، بسیار ساده می‌شود.

برای تخصیص کنترل‌گر به یک لایه‌ی نمایش، انگولار از دو روش پشتیبانی می کند.

  1. کنترل‌گر بعنوان نام‌خاصیت
  2. کنترل‌گر بعنوان مدیریت‌کننده‌ی $scope

کنترل‌گر بعنوان نام‌خاصیت (Controller as propertyName)

همانطور که در مستندات API برای ng-controller آمده است، می‌توان یک کنترل‌گر را بعنوان یک نام‌خاصیت در آرگومان ng-controller معرفی کرد. البته در نظر داشته باشید که برای اینکار باید نسخه‌ی انگولارتان ۱٫۲ و یا بالاتر باشد.

<p ng-controller="MessageController as controller">
{{controller.message}}
</p>

دیدید به چه راحتی داده‌های مدل را با استفاده از کنترلر آماده کردیم.

اگرچه این روش، یعنی تخصیص مستقیم خواص به this سر راست است، اما اینکه کل کنترل‌گر را در اختیار لایه‌ی نمایش قرار دهیم، این احساس گمراه‌کننده را القا می‌کند که کنترل‌گر بخشی از مدل است، در حالیکه نقش اصلی کنترل‌گر تنها آماده سازی مدل است. آزمون و عیب‌یابی عموما هنگامی که دسترسی را تنها به مواردی که مورد نیاز استفاده کننده است محدود کنیم، آسان‌تر است. همچین دنبال کردن این روش به کد لایه‌ی نمایش شلوغی اضافه می‌کند، چون کل خواص می‌بایست با ارجاء به کنترل‌گر فراخوانی شوند. (یعنی استفاده از نام کنترل‌گر سپس نقطه . و سپس نام خاصیت). در حالیکه کد لایه‌ی نمایش عموما بحرانی‌ترین بخش از اپلیکیشن از نظر پیچیدگی می‌باشد. و اولین بخشی می‌باشد که فهم آن با یک نگاه به کد با مشکل روبرو می‌شود. در نهایت، کنترل‌گرها دست در دست حوزه عمل می‌کنند، در نتیجه برای مقاصد آموزشی اینکه ارجاءای به حوزه (Scope) داشته باشیم راه‌گشا است. بدین‌صورت ما می‌توانیم تنها آن‌چیزهایی را که می‌خواهیم در دسترس لایه‌ی نمایش قرار دهیم. برای همین، این دوره‌ی آموزشی نحوه‌ی تعریف کنترلر را به نحوی که شیء حوزه ($scope) را مدیریت می‌کند ترجیح می‌دهد.

این روش تخصیص Controller نیز در بین جامعه‌ی انگولار پر‌ استفاده‌تر است. حتی مستندات اصلی خود Angular نیز از این روش استفاده نموده است. با این‌حال استفاده از روش نام‌خاصیت دارای نکات مثبتی نیز می‌باشد که از آن می‌توان به موارد زیر اشاره کرد:

  • استفاده از controller as باعث می‌شود که فهمیدن اینکه متد یا خاصیت کدام کنترل‌گر را در لایه‌ی نمایش استفاده می‌کنیم، ساده تر شود. این مورد برای المان‌هایی است که بیش از یک کنترل‌گر به آنها تخصیص داده شده مفید است.
  • اگر شما کنترل‌گرتان را به شکل تابع سازنده می‌نویسید، دسترسی سریعتری به متد‌ها و خاصیت‌های آن دارید. چون در درون خود کلاس بدون نیاز به استفاده از $scope می‌توانید به آنها دسترسی داشته باشید.

تصیمیم راجع به اینکه کدام روش را باید برگزید علاوه به سلیقه، به نحوه‌ی نوشتن کد‌های اپلیکیشن، حجم آن، اینکه المانی در اپلیکیشن داریم که بیش از یک کنترل‌گر به آن تخصیص داده شده است و در نهایت اینکه هدف کدی که می‌زنیم چه چیز است، بستگی دارد.

خب پس از اینکه این روش را برای استفاده از کنترل‌گر انتخاب کردیم، این سوال‌های اساسی پیش می‌آید. “چگونه می‌توانیم به یک ارجاع به این شی‌ء حوزه دسترسی داشته باشیم؟”، “آیا آنرا با عملگر new می‌سازیم؟” و “آیا آنرا از جایی درخواست می‌کنیم؟”.

تزریق وابستگی‌ Dependency Injection

جواب تمام سوال‌ها این است: “آنرا از طریق تزریق وابستگی بدست می‌آوریم”. نکته دیگری که وجود دارد این است که ما کدی برای ساخت یک نمونه (Instance) از روی کنترل‌گر-مان، همچون controller = new messageController() ننوشتیم. پس چه کسی کنترل‌گرهایی که در لایه‌ی نمایش مورد استفاده قرار می‌گیرد را می‌سازد؟

خود Angular مطمعنا! AngularJS از روش طراحی وارونگی کنترل (Inversion of Control) تبعیت می‌کند. AngularJS یک ظرف وارونگی کنترل است که مدیریت چرخه‌زندگی (Lifecycle) کامپوننت‌های برنامه را برعهده می‌گیرد. در نتیجه، وقتی که یک کنترل‌گر جدید در هر کامپوننت دیگری نیاز است، خود انگولار آنرا می‌سازد. این عمل علاوه بر اینکه کار برنامه نویس را کمتر می‌کند، بلکه مهمتر از آن، به انگولار این قابلیت را می‌دهد تا منابع یا وابستگی‌ها را به کامپوننت‌های ما تزریق (Inject) کند.

وارونگی کنترل: در روش سنتی نوشتن رویه‌ای برنامه‌ها، جریان اصلی برنامه را کد‌های اختصاصی برنامه‌نویس مشخص می‌کند و برای وظایف مورد نیازی که یک برنامه نیاز دارد، این کد‌های اختصاصی، کتابخانه‌های مورد نیاز را فرا‌‌می‌خواند و از‌ آنها استفاده می‌کند. بعنوان مثال در همین جاوااسکریپت، وقتی می‌خواهیم یک درخواست AJAX بفرستیم، می‌آییم کتابخانه jQuery را لود می‌کنیم، سپس تابع $.ajax آنرا فرا‌می‌خوانیم و درخواستمان را می‌فرستیم. اما در طراحی وارونگی کنترل، همانطور که از اسمش بر‌ می‌آید، کنترل جریان برنامه برعکس می‌شود و این کتابخانه‌ها هستند که جریان اصلی برنامه را مدیریت می‌کنند و هر کجا که لازم شد، کد اختصاصی نوشته شده توسط برنامه‌نویس را فرا می‌خوانند.
کامپوننت: به بخش‌هایی از برنامه که کلیه‌ی داده‌ها، متغییر‌ها و توابع موجود در آن به هم ارتباط دارند و برای یک هدف خاص نوشته شده‌اند گفته می‌شود. بطور مثال کلیه‌ی توابع و متغییر‌هایی که در جی‌کوئری برای درخواست‌های AJAX نوشته شده است را می‌توان بعنوان یک کامپوننت مشخص نمود.

$scope شیء

بعنوان یک کامپوننت که توسط فریمورک تزریق وابستگی مدیریت می‌شود، کنترل‌گر ما تنها به اضافه شدن یک پارامتر که به نام $scope شناخته می‌شود نیاز دارد. نام این پارامتر بسیار مهم است. اینقدر مهم، که اگر در طی پروسه‌ی ساخت (Build) شما کد‌های جاوااسکریپت را Minify کنید، مکانسیم تزریق وابستگی را مختل می‌کنید. (نگران نباشید، یک راه‌حل برای این مشکل وجود دارد که در بخش تزریق وابستگی به آن خواهیم پرداخت.)

function MessageController($scope)
{
$scope.message = "This is a model.";
}

با اضافه کردن پارامتر $scope به تابع سازنده‌ای که قبلا تعریف کرده‌ایم، به AngularJS می‌گوییم که ما یک ارجاء به حوزه‌ی‌ای که به لایه‌ی نمایش‌مان اختصاص داده شده است برای کنترل‌گرمان نیاز داریم. حالا، بجای اینکه خاصیت messeage را به this (یا همان کنترل‌گرمان) اختصاص دهیم، آنرا مستقیم به حوزه‌ی داده شده اختصاص می‌دهیم.

همچنین در قالب می‌بایست عبارت as controller را از آرگومان رهنمود ng-controller حذف کنیم. همچنین عبارت controller.message به message تنها تبدیل می‌شود، که همان خاصیتی است که به حوزه اختصاص داده بودیم.

<p ng-controller="MessageController">
{{message}}
</p>

مدل-نمایش-کنترل‌گر Model-View-Controller

مفهموم کنترل‌گر از آنچه که در مستندات اصلی دریافتیم، شامل افزودن قابلیت‌ها به لایه‌ی نمایش نیز بود. قبل از اینکه به این بخش برویم، به نظرم بد نباشد که کمی راجع به تفاوت کنترل‌گر Angular با آنچه که در الگوی MVC کلاسیک می‌شناسیم صحبت کنیم. (یا می‌توانید این بخش را نادیده بگیرید و مستقیم به بخش بعدی، یعنی قابلیت‌ها بروید.)

با توجه به مقاله‌ی موجود در ویکی‌پدیا برای الگوی MVC، یک کنترل‌گر “واسطی میان ورودی‌ها می‌باشد، که آنها را به دستوراتی برای مدل و نمایش تبدیل می‌کند”. اما، فهم بخش “دستوراتی برای مدل و نمایش” این تعریف در زمینه (Context) انگولار، به این دلیل که نسخه‌ای که انگولار از MVC پیاده‌سازی کرده است ساده سازی شده است، سخت است. در پیاده‌سازی Angular از مفهوم مدل‌های ضعیف (Anemic Models)، به معنی مدل‌هایی که شامل هیچ بخش منطق‌ای نیستند، استفاده شده است. در نتیجه در AngularJS، بخصوص در این زمان، روش غالب، قرار دادن کلیه‌ی منطق اپلیکیشن (Business logic) در درون کنترل‌گر است. به عبارت دیگر، اپلیکشن‌های انگولار به سمت مدل‌های لاغر و کنترل‌گر‌های چاق پیش‌ می‌روند.

قابلیت‌ها

بیایید با هم یک کنترل‌گر با یک تابع ساده بنویسیم تا امتحان کنیم که آیا می‌توانیم در لایه‌ی نمایش آنرا فرا بخوانیم؟ اگر از بخش مبانی بیاد داشته باشید، AngularJS به ما اجازه نمی‌دهد تا یک تابع را در لایه‌ی نمایش تعریف و تخصیص دهیم.

کنترل‌گر زیر، یک تابع ساده را به حوزه تخصیص می‌دهد.

function CountController($scope)
{
$scope.count = function ()
{
return 12;
}
}
view raw count-controller.js hosted with ❤ by GitHub

فراخوانی تابع در درون یک عبارت، کاملا شبیه با جاوااسکریپت معمولی است. تنها کافیست از () در جلوی نامش استفاده کنیم.

<p ng-controller="CountController">
There are {{count()}} months in a year.
</p>

در نظر داشته باشید که تابع فراخوانی نمی‌شود و به سادگی فراموش شود، بلکه در حقیق به مدل منتسب می‌شود. این انتساب به چه معنی است؟ خب، زیرساخت انقیاد در انگولار‌جی‌اس بگونه‌ای است که انگولار نه تنها وقتی که برای بار اول که لایه‌ی نمایش رندر می‌شود تابع را فرا‌ می‌خواند، بلکه هرزمان که مدلی که به آن منتسب شده است تغییر می‌کند هم فراخوانی می‌شود. برای اینکه این موضوع را در عمل ببینیم، باید یک تابع را که از خواصی که به مدل‌مان منتصب شده است، استفاده می‌کند بنویسیم. تابع add که در پایین آمده است از دو خاصیت مدل که به حوزه منتصب شده است، استفاده می‌کند، operand1 و operand2. انگولار هر زمان‌که یکی یا هردوی این خواص تغییر کند، تابع را فرا می‌خواند و نتایج را رندر می‌کند.

function AdditionController($scope)
{
$scope.operand1 = 0;
$scope.operand2 = 0;
$scope.add = function ()
{
return $scope.operand1 + $scope.operand2;
}
$scope.options = [0, 1, 2, 3, 4];
}

حالا بیایید با استفاده از ورودی select، مقادیر را تغییر دهیم و ببینیم چه می‌شود. ممکن است در خط آخر کنترل‌گر ما که در بالا آمده است مشاهده کرده باشید که تعدادی گزینه‌ را برای selectمان آماده سازی کرده‌ایم. خواهیم دید که چگونه به روش Angular این گزینه‌ها را در لایه‌ی نمایش، استفاده کنیم.

<p ng-controller="AdditionController">
<select ng-model="operand1" ng-options="x for x in options"></select>
+ <select ng-model="operand2" ng-options="x for x in options"></select>
= {{add()}}
</p>

در مثال بالا دیدید که با استفاده از رهنمود ng-options گزینه‌هایی که آماده کرده بودیم را به select دادیم تا از آنها استفاده کند. آرگومان که برای ng-options‌ نوشته‌ایم یعنی x for x زائد بنظر می‌آید، چون تنها لیست اصلی مقادیر را بر‌ می‌گرداند، با این وجود این رهنمود ما را ملزم کرده است که این بخش را حتما بنویسیم.

هنگامی که مدل آرایه‌ای از Object‌ها باشد، چیزی که بیشتر مرسوم است، شاید بخواهید عبارتی را بنویسید که برای مثال خاصیت name را برای لیبیل گزینه برگزیند. برای اینکار بجای x می‌توانید از x.name استفاده کنید. برای اطلاعات بیشتر راجع به پارامتر‌های رهنمود select به مستندات AngularJS مراجعه کنید

خب به خوبی عمل کرد! با این‌حال، طراحی تابع add را می‌توان با کلیت بخشیدن به آن بهبود بخشید. با اینکار می‌توان این تابع را بگونه‌ای بهبود بخشید که با آن بتوان هر دو عددی که خواستیم را جمع کنیم و وابسته با operand1 و operand2 در شیء حوزه نباشد.

function AdditionController($scope)
{
$scope.number = 2;
$scope.add = function (operand1, operand2)
{
return operand1 + operand2;
}
}

درون عبارت، شما می‌توانید هم خاصیت‌ها و هم رشته‌ها را به توابع بدهید، دقیقا شبیه آنچه که در جاوااسکریپت می‌شود انجام داد.

<p ng-controller="AdditionController">
{{add(number, 2)}} is not the same as {{add(number, "2")}}
<br>
2 + 2 + 2 + 2 = {{add(2, add(2, add(2, 2)))}}
</p>

حالا بیایید یک تابع callback را که به یک کنش کاربر رسیدگی می‌کند بنویسیم.

Callbacks

یک مثال در بخش مبانی وجود دارد که با استفاده از رهنمود ng-click یک مقدار بولی را در مدل تغییر وضعیت می‌دادیم. در آنجا ابتدا خاصیت notSubmitted را درون رهنمود ng-init مقدار دهی اولیه می‌کردیم، سپس با استفاده از یک callback خطی و ساده آنرا تغییر وضعیت می‌دادیم. notSubmitted = ! notSubmitted. بیایید حالا آن مثال را بهبود ببخشیم و مقدار دهی اولیه و منطق تغییر وضعیت را به جایگاه اصلی اش، یعنی یک کنترل‌گر ببریم.

function FormSubmitController($scope)
{
$scope.notSubmitted = true;
$scope.toggle = function ()
{
$scope.notSubmitted = !$scope.notSubmitted
};
}

حالا که toggle یک تابع است که در حوزه قابل دسترسی است، آرگومان رهنمود ng-click بیشتر شبیه به فراخوانی یک تابع است: toggle().  البته این به معنی فراخوانی بلافاصله نمی‌باشد. بلکه تا زمانیکه کاربر کلیک نکرده باشد، فقط یک رشته است و پس از آن تفسیر و اجرا می‌شود.

<div id="form_wrapper" ng-controller="FormSubmitController">
<form ng-show="notSubmitted">
<input type="text" name="feedback"/>
<input type="submit" value="Submit Feedback" ng-click="toggle()"/>
</form>
<div ng-hide="notSubmitted">Thanks for submitting your feedback!</div>
</div>

مثال به خوبی عمل می‌کند و منطق تغییر وضعیت ما الان در جای بهتری است. چرا بهتر؟ سوال خوبیست. آموزش‌ها و کتاب‌های آموزشی در بیشتر اوقات روش‌هایی که برای مدیریت پیچیدگی هستند را با مثال‌هایی که برای نشان دادن این برتری بسیار ساده هستند، نشان می‌دهند. این آموزش هم از آنها مستثنی نیست. در بخش قبلی، مبانی، از شما خواستم که از قضاوت کردن راجع به AngularJS بخاطر استفاده از عبارات در HTML خودداری کنید. اگر شما از راهی که انگولار برای توسعه بخشیدن به HTML با اضافه کردن رفتار پویا به آن ناراحت شده بودید، اکنون می‌توانید به خوبی آن‌چیزی که باعث می‌شود پیچیدگی‌ها را به کنترل‌گر‌ها اضافه کنیم درک کنید.

آزمون کردن راحت‌تر یکی از دلایل کلاسیک برای منتقل کردن کد از یک بخش پیچیده (قالب) به یک بخش ساده تر (کنترل‌گر) است. همچنین شما نمی‌توانید هر‌آنچه را که انتظار دارید در درون قالب وارد کنید. همچنین برتری رسیدگی به کنش‌های کاربر در درون کنترل‌گر زمانی‌که کدی برای یک رفتار پیچیده می‌نویسیم بیشتر به بچشم می‌آید. بطور مثال همگام‌سازی داده‌های مدل با یک سرور، از راه دور.

نتیجه گیری

در این بخش، ما کد جاوااسکریپت را به اپلیکیشن AngularJSمان اضافه کردیم. اینکار به شکل یک کنترل‌گر بود، که در الگوی MVC وظیفه‌اش آماده سازی داده برای لایه‌ی نمایش است. کنترل‌گر‌ها داده‌ها را با تخصیص دادن خواص به شیء حوزه در اختیار لایه‌ی نمایش می‌گذارند. در بخش بعدی دوره آموزش AngularJS، نگاه جزئی‌تری به اشیاء حوزه‌ (Scope Objects) خواهیم داشت و یاد خواهیم گرفت که چگونه این اشیاء به شکل سلسه مراتبی همچون DOM اپلیکیشن‌مان سازمان می‌یابند. لازم به یادآوری است که علاوه بر مشاهده و ویرایش آنلاین کد‌های این بخش، می‌توایند کد آنرا از مخزن Githubای که برای این دوره ساخته شده است، دانلود کنید.