مطالب
آشنایی با Bower
با توجه به رشد روز افزون وب و مراحل تکامل برنامه نویسی آن ، نیاز به ابزارهایی که نصب ، به روز رسانی و مدیریت کتابخانه‌ها و ابزارهای جانبی استفاده شده در پروژه‌ها را بطور خودکار انجام دهند بیش از پیش احساس میشود. Bower یکی از ابزارهایی است که برای کمک به این امر معرفی شده است.
bower  
Bower چیست؟
Bower یک package manager برای فن آوری‌های سمت کلاینت است.توانایی نصب ، جستجو و حذف کتابخانه‌های Javascript،HTML،CSS دارد.

مزایا
:
  1. نصب ابزارها و کتابخانه‌ها توسط  یک خط فرمان!
  2. به جای اینکه در سایتهای مختلف ورژن کتابخانه‌ها را پیگیری کنید و update شدن یا نشدن آنها را بررسی نمایید(مثلا آیا  jQueryمورد استفاده درپروژه ، آخرین نسخه است؟) ، با استفاده از Bower در کمترین زمان ممکن این کار را انجام دهید.
  3. نصب آفلاین. وقتی کتابخانه ای برای اولین بار نصب شود کش شده و دفعات بعد برای نصب همان کتابخانه(و البته همان ورژن) از کش استفاده خواهد کرد.(مگر اینکه کاربر صراحتا کش را خالی کرده باشد).
  4. نصب کتابخانه‌های وابسته. اگر کتابخانه ای وابسته به کتابخانه‌های دیگر باشد (مثل وابستگی Twitter Bootstrap به jQuery)، بطور خودکار وابستگی‌ها نیز نصب می‌گردند.
مراحل نصب :
قبل از نصب باید دو ابزار زیر در سیستم نصب شده باشند:
  1. Nodejs  
  2. Git  : برخی از کتابخانه‌ها باید از مخزن Git واکشی شوند.
نصب Bower :
در خط فرمان دستور زیر را اجرا نمایید:
 npm install -g bower 
دستور بالا Bower را بصورت global نصب خواهد کرد و اکنون میتوان کتابخانه‌های مختلف را نصب نمود.

نصب کتابخانه ها:

برای نصب کتابخانه‌ها از دستور زیر استفاده می‌شود:
bower install <package>
برای مثال برای نصب کتابخانه angularjs باید دستور زیر را اجرا نمود:
 bower install angular 
یا jQuery:
 bower install jquery 
ممکن است نیاز باشد تا ورژن خاصی از یک کتابخانه را نصب کنید که در این صورت باید مانند مثال زیر عمل کرد:
bower install <package>#<version>
bower install jquery#1.7.0
دستور فوق نسخه 1.7.0 jQuery را نصب خواهد کرد.

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

bower_components/
jquery/
   README.md
   bower.json
   component.json
   composer.json
   jquery-migrate.js
   jquery-migrate.min.js
   jquery.js
   jquery.min.js
   jquery.min.map
   package.json

و در نهایت نحوه استفاده:
<script type="text/javascript" src="bower_components/jquery/jquery.js"></script>

جستجو در کتابخانه ها:
Bower امکان جستجو در کتابخانه‌های ثبت شده را می‌دهد. مثال:
bower search bootstrap
Search results:
bootstrap git://github.com/twbs/bootstrap.git
angular-bootstrap git://github.com/angular-ui/bootstrap-bower.git
sass-bootstrap git://github.com/jlong/sass-twitter-bootstrap.git  
مطالب
مسیریابی تو در تو در Angularjs با استفاده از UI-Router

UI-Router   ابزاری برای مسیریابی در AngularJS است که این امکان را برایتان فراهم می‌کند تا بخش‌های برنامه رابط کاربریتان را به شکل یک ماشین حالت ساماندهی کنید. برخلاف سرویس route$ که بر اساس مسیریابی URL‌ها ساماندهی شده و کار می‌کند، UI-Router بر اساس حالت‌ها کار می‌کند، که این حالت‌ها می‌توانند در صورت لزوم مسیریابی هم داشته باشند.


UI-Router یکی از افزونه‌های مجموعه Angular-ui، و پاراگراف بالا معرفی آن در صفحه خانگیش است (تقریبا!). این افزونه جزئیات مفصلی دارد و در این مطلب تنها به معرفی آن خواهم پرداخت (بر اساس مطالب صفحه خانگیش). پیش از ادامه پیشنهاد می‌کنم اگر مطالب زیر را نخوانده‌اید ابتدا آن‌ها را مرور کنید:
برای استفاده از UI-Router باید:
  1. فایل جاوا اسکریپت آن را دانلود کنید (released یا minified).
  2. در صفحه اصلی برنامه‌تان پس از include کردن فایل اصلی AngularJS فایل angular-ui-router.js (یا angular-ui-router.min.js) را include کنید.
  3. 'ui.router' را به لیست وابستگی‌های ماژول اصلی اضافه کنید.
نتیجه چیزی شبیه این خواهد بود:
<!doctype html>
<html ng-app="myApp">
<head>
    <script src="//ajax.googleapis.com/ajax/libs/angularjs/1.1.5/angular.min.js"></script>
    <script src="js/angular-ui-router.min.js"></script>
    <script>
        var myApp = angular.module('myApp', ['ui.router']);
        // For Component users, it should look like this:
        // var myApp = angular.module('myApp', [require('angular-ui-router')]);
    </script>
    ...
</head>
<body>
    ...
</body>
</html>

حالت‌ها و viewهای تو در تو

قابلیت اصلی UI-Router امکان تعریف حالت‌ها و vieweهای تو در تو است. در مطلب مسیریابی در AngularJs #بخش اول دایرکتیو ng-view معرفی شده است. هنگام استفاده از سرویس route$ با این دایرکتیو می‌توان محل مورد نظر برای بارگذاری محتویات مربوط به مسیرها را مشخص کرد. دایرکتیو ui-view در UI-Router همین نقش را دارد. فرض کنید این کد فایل index.html باشد:
<!-- index.html -->
<body>
    <div ui-view></div>
    <!-- We'll also add some navigation: -->
    <a ui-sref="state1">State 1</a>
    <a ui-sref="state2">State 2</a>
</body>
همانطور که ملاحظه می‌کنید در تگ‌های a از دایرکتیو ui-sref استفاده شده است. این دایرکتیو علاوه بر مدیریت تغییر حالت، خصوصیت href تگ a را در صورتی که حالت مشخص شده URL داشته باشد تولید می‌کند. البته برای استفاده از UI-Router ملزم به استفاده از دایرکتیو ui-sref نیستید و می‌توانید href را مشخص کنید. ولی با استفاده از ui-sref لازم نیست مسیر یک حالت را به یاد داشته باشید، و یا در صورت تغییر آن، همه hrefها را به روز کنید.
در ادامه برای هر کدام از حالت‌ها یک template اضافه می‌کنیم:
فایل state1.html:
<!-- partials/state1.html -->
<h1>State 1</h1>
<hr/>
<a ui-sref="state1.list">Show List</a>
<div ui-view></div>
فایل state2.html:
 <!-- partials/state2.html -->
<h1>State 2</h1> 
<hr /> 
<a ui-sref="state2.list">Show List</a> 
<div ui-view></div>

دو نکته قابل توجه در این templateها وجود دارد. اول اینکه همانطور که می‌بینید templateها خود شامل تگی با دایرکتیو ui-view هستند. و دوم مقدار دایرکتیو ui-sref است که به صورت state1.list و state2.list آمده است. این جدا سازی با نقطه نشان دهنده سلسله مراتب حالت‌هاست. یعنی حالت‌های state1 و state2 هرکدام حالت فرزندی به نام list دارند. در ادامه وقتی حالت‌ها و مسیریابی را در ()app.config تعریف کنیم این مسائل از هاله‌ای از ابهام که در آن هستند خارج می‌شوند! فعلا بیاید با راهنمای UI-Router پیش برویم و فایل‌های template حالت‌های فرزند را تعریف کنیم. templateهایی که قرار است در ui-view پدرانشان بارگذاری شوند:
<!-- partials/state1.list.html -->
<h3>List of State 1 Items</h3>
<ul>
  <li ng-repeat="item in items">{{ item }}</li>
</ul>

<!-- partials/state2.list.html -->
<h3>List of State 2 Things</h3>
<ul>
  <li ng-repeat="thing in things">{{ thing }}</li>
</ul>
خوب! حالا برویم سراغ شعبده بازی! برای اینکه از UI-Router استفاده کنید لازم است stateProvider$ و urlRouterProvider$ را به عنوان وابستگی به ()app.config تزریق کنید:
myApp.config(['$stateProvider', '$urlRouterProvider',
function($stateProvider, $urlRouterProvider) {
  //
  // For any unmatched url, redirect to /state1
  $urlRouterProvider.otherwise("/state1");
  //
  // Now set up the states
  $stateProvider
    .state('state1', {
      url: "/state1",
      templateUrl: "partials/state1.html"
    })
    .state('state1.list', {
      url: "/list",
      templateUrl: "partials/state1.list.html",
      controller: function($scope) {
        $scope.items = ["A", "List", "Of", "Items"];
      }
    })
    .state('state2', {
      url: "/state2",
      templateUrl: "partials/state2.html"
    })
    .state('state2.list', {
      url: "/list",
        templateUrl: "partials/state2.list.html",
        controller: function($scope) {
          $scope.things = ["A", "Set", "Of", "Things"];
        }
      })
    }]);
در ابتدا با متد ()urlRouterProvider.otherwise$ مسیر پیشفرض مشخص شده است. متد otherwise را باید از مقالات مسیریابی در AngularJS به یاد داشته باشید. سپس حالت‌های برنامه با استفاده از متد state تعریف شده است. این متد دو پارامتر ورودی دارد؛ اولی نام حالت و دومی یک شی شامل خصوصیات حالت. همانطور که می‌بینید این شی خصوصیاتی شبیه به همان‌ها که در متد ()routeProvider.when$ وجود داشت دارد. می‌شود گفت این خصوصیات همان‌ها هستند و همان عملکرد را دارند.
خصوصیت url مشخص کننده مسیر حالت است. این خصوصیت همان مقداریست که به عنوان پارامتر اول به ()routeProvider.when$ پاس می‌شد. در این پارامتر می‌شود متغیرهای url را هم به همان ترتیب تعریف کرد. مثلا اگر حالت state1 در آدرسش یک پارامتر id داشته باشد می‌شود آن را به این ترتیب تعریف کرد:
.state('state1', {
      url: "/state1/:id",
      templateUrl: "partials/state1.html"
    })
برای خواندن مقدار این متغیر باید از stateParams$ استفاده کرد:
$stateParams.id
به خصوصیت url دو حالت state1.list و state2.list دقت کنید. هردو برابر 'list/' است. یعنی هردو یک مسیر دارند؟ نه! بلکه مسیر state1.list برابر '/state1/list' و مسیر state2.list برابر '/state2/list' است. در واقع حالت state1.list یعنی list فرزند state1 و به همین ترتیب state2.list یعنی list فرزند state2. و می‌توان گفت UI-Router آدرس url حالت فرزند را، آدرسی نسبی، نسبت به url حالت پدر می‌داند. این رابطه سلسله مراتبی و پدر و فرزندی را می‌توان با استفاده از خصوصیت parent به صورت صریح‌تری مشخص کرد:
.state('list', {
    parent: "state1",
    url: "/list",
    templateUrl: "partials/state1.list.html",
    controller: function($scope) {
        $scope.items = ["A", "List", "Of", "Items"];
    }
})
.state('list', {
    parent: "state2",
    url: "/list",
    templateUrl: "partials/state2.list.html",
    controller: function($scope) {
        $scope.items = ["A", "List", "Of", "Items"];
    }
})
تا اینجای کار، اگر آدرس "state1/" وارد شود، فایل "partials/state1.html" در "ui-view" فایل "index.html" بارگذاری خواهد شد. اگر آدرس "state1/list/" وارد شود، ابتدا فایل "partials/state1.html" در "ui-view" فایل "index.html" بارگذاری شده، سپس فایل "partials/state1.list.html" در "ui-view"  آمده در فایل فایل "partials/state1.html" بارگذاری می‌شود. این همان امکان حالت‌ها و viewهای تو در تو است که UI-Router فراهم می‌کند. 
اینجا می‌توانید خروجی کدهای بالا را مشاهده کنید.
اگر مستقیما url یک حالت فرزند وارد شود، یا به عبارت دیگر، اگر بخواهیم مستقیما برنامه به حالتی که فرزند حالت دیگر است برود، UI-Router برنامه را ابتدا به حالت پدر، و پس از آن به حالت فرزند خواهد برد. حالت فرزند دو چیز را از حالت پدر به ارث می‌برد:
  1. وابستگی‌های فراهم شده در حالت پدر به وسیله "resolve"
  2. داده‌های سفارشی مشخص شده در خصوصیت data حالت پدر
استفاده از resolve در UI-Router مشابه استفاده از آن در route$  است. ولی افزودن داده‌های سفارشی کمی متفاوت است. برای افزودن داده‌های سفارشی باید از خصوصیت data یک حالت استفاده کرد:
.state('state1', {
    url: "/state1",
    templateUrl: "partials/state1.html",
    data:{
        foodata: 'addorder'
    }
})
برای دسترسی به این داده‌ها هم می‌توان از state.current.data$ استفاده کرد:
$state.current.data.foodata


Viewهای نامگذاری شده و چندگانه

یکی دیگر از قابلیت‌های کاربردی UI-Router امکان داشتن چند ui-view در هر template است (استفاده همزمان از این قابلیت و حالت‌های تو در تو، امکان مدیریت واسط کاربری را به خوبی فراهم می‌کند).  برای توضیح این قابلیت، با راهنمای UI-Router همراه شویم:
1. دستورالعمل برپایی UI-Router که در بالا آمده را اجرا کنید.
2. یک یا چند ui-view به برنامه‌تان اضافه کنید و آن‌ها را نامگذاری کنید:
<!-- index.html -->
<body>
    <div ui-view="viewA"></div>
    <div ui-view="viewB"></div>
    <!-- Also a way to navigate -->
    <a ui-sref="route1">Route 1</a>
    <a ui-sref="route2">Route 2</a>
</body>
3. حالت‌های برنامه‌تان را در روال config ماژول تعریف کنید:
myApp.config(function ($stateProvider) {
    $stateProvider
      .state('index', {
          url: "",
          views: {
              "viewA": { template: "index.viewA" },
              "viewB": { template: "index.viewB" }
          }
      })
      .state('route1', {
          url: "/route1",
          views: {
              "viewA": { template: "route1.viewA" },
              "viewB": { template: "route1.viewB" }
          }
      })
      .state('route2', {
          url: "/route2",
          views: {
              "viewA": { template: "route2.viewA" },
              "viewB": { template: "route2.viewB" }
          }
      })
});
4. خروجی کدهای بالا را اینجا مشاهده کنید.


چند نکته

UI-Router جزئیات فراوانی دارد و آنچه آمد تنها پرده برداری از آن بود. دلم می‌خواست می‌توانستم بیش از این آن را معرفی کنم، اما متاسفانه این روزها وقت آزاد کافی ندارم. در انتها می‌خواهم به چند نکته اشاره کنم:
روش controller as
برای استفاده از روش controller as در UI-Router باید به این ترتیب عمل کنید:
.state('list', {
    parent: "state1",
    url: "/list",
    templateUrl: "partials/state1.list.html",
    controller: "state1ListController as listCtrl1"
    }
})
.state('list', {
    parent: "state2",
    url: "/list",
    templateUrl: "partials/state2.list.html",
    controller: "state2ListController as listCtrl2"
    }
})

حالت‌های انتزاعی

حالت انتزاعی حالتی است که url ندارد و در نتیجه برنامه نمی‌تواند در آن حالت قرار گیرد. حالت‌های انتزاعی بسیار به درد خور هستند! مثلا فرض کنید چند حالت دارید که اشتراکاتی با هم دارند (همه باید در template مشابهی بارگذاری شود، یا وابستگی‌های یکسانی دارند، یا حتی سطح دسترسی یکسان). با تعریف یک حالت انتزاعی و جمع کردن همه وابستگی‌ها در آن، و تعریف حالت‌های مورد نظرتان به عنوان فرزندان حالت انتزاعی، می‌توانید اشتراکات حالت‌های برنامه را ساده‌تر مدیریت کنید.

حساسیت به حروف بزرگ و کوچک

در سرویس route$ با مقداردهی خصوصیت caseInsensitiveMatch می‌توانستیم مشخص کنیم که بزرگ و کوچک بودن حروف در تطبیق آدرس صفحه با پارامتر route در نظر گرفته بشود یا نه. خودمانیش اینکه url به حروف بزرگ و کوچک حساس باشد یا نه. متاسفانه در UI-Router از این امکان خبری نیست (البته فعلا) و آدرس‌های تعریف شده به حروف بزگ و کوچک حساس هستند.
 اینجا روشی برای حل این مشکل پیشنهاد شده، به این ترتیب که همه url‌های وارد شده به حروف کوچک تبدیل شود (راستش من این راه حل را نمی‌پسندم!).
چند روز قبل هم تغییراتی در کد UI-Router داده شده که امکان حساس نبودن به حروف کوچک و بزرگ فراهم شود. این تغییر هنوز در نسخه نهایی فایل UI-Router نیامده است. هرچند اگر بیاید هم آنچه تا امروز (23 اسفند 92) انجام شده مشکل را حل نمی‌کند.
اگر شما هم مثل من می‌خواهید کلا آدرس‌ها به حروف بزرگ و کوچک حساس نباشند، و فرصت حل کردن اساسی مشکل را هم ندارید به این ترتیب عمل کنید:
  • در فایل "angular-ui-router.js" عبارت "new RegExp(compiled)" را پیدا کرده و آن را به  "RegExp(compiled, 'i')" تبدیل کنید. و یا در "angular-ui-router.min.js" (هرکدام از فایل‌ها که استفاده می‌کنید) عبارت new RegExp(o) را پیدا کرده و آن را به new RegExp(o, "i")  تبدیل کنید. همین؛ صدایش را هم در نیاورید!


مطالب
AngularJS #1
پیش از اینکه آموزش AngularJs را شروع کنیم بهتر است با مفهوم برنامه‌های تک صفحه ای وب  و یا  Single Page Web Applications آشنا شویم؛ چرا که AngularJS برای توسعه هر چه ساده‌تر و قوی‌تر این گونه برنامه‌ها متولد شده است.

Single Page Application
برای درک چگونگی کارکرد این برنامه ها، مثالی را میزنیم که هر روزه با آن سرو کار دارید، یکی از نمونه‌های کامل و قدرتمند برنامه‌های Single Page Application و یا به اختصار SPA، سرویس پست الکترونیکی Google و یا همان Gmail است.
اجازه بدهید تا ویژگی‌های SPA را با بررسی Gmail انجام دهم، تا به درک روشنی از آن برسید:

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

تغییر URL در نوار آدرس مرورگر
وقتی شما بر روی یک ایمیل کلیک می‌کنید و آن ایمیل را بدون Reload شدن مجدد صفحه مشاهده می‌کنید، آدرس صفحه در مرورگر نیز تغییر می‌کند. خب مزیت این ویژگی چیست؟ مزیت این ویژگی در این است که هر ایمیل شما دارای یک آدرس منحصر به فرد است و به شما امکان Bookmark کردن آن لینک، باز کردن آن در یک Tab جدید و یا حتی ارسال آن به دوستان خود را دارید. حتی اگر این مطلب را جدا از Gmail در نظر بگیریم، به موتور‌های جست و جو کمک می‌کند، تا هر صفحه را جداگانه Index کنند؛ جدا از اینکه وبسایت ما SPA است. همچنین این کار یک مزیت مهم دیگر نیز دارد؛ و آن کار کردن کلیدهای back و forward مرورگر، برای بازگشت به صفحات پیمایش شده قبلی است.
شاید قبل از بیان این ویژگی با خود گفته باشید که پیاده سازی Reload نشدن صفحات با AJAX آن چنان کار پیچیده ای نیست. بله درست است، اما آیا شما قبل از این راه حلی برای تغییر URL اندیشیده بودید؟ مطمئنا شما هم صفحات وب زیادی را دیده اید که همه‌ی صفحات آن دارای یک URL در نوار آدرس مرورگر هستند و هیچگاه تغییر نمی‌کنند و با باز کردن یک لینک در یک Tab جدید، باز همان صفحه‌ی تکراری را مشاهده می‌کنند! و یا بدتر از همه که دکمه‌ی back مرورگر غیر عادی عمل می‌کند. بله، اینها تنها تعدادی از صدها مشکلات رایج سیستم‌های نوشته شده ای است که سعی کردند همه‌ی کارها در یک صفحه انجام شود.

Cache شدن اطلاعات دریافتی
شاید خیلی‌ها ویژگی‌های فوق را برای یک SPA کافی بدانند، اما تعدادی هم مانند نگارنده وجود یک کمبود را حس می‌کنند و آن کش شدن اطلاعات دریافتی در مرورگر است. Gmail این امکان را به خوبی پیاده سازی کرده است. لیست ایمیل‌های دریافتی در بار اول از سرور دریافت می‌شود، سپس شما بر روی یک ایمیل کلیک و آن را مشاهده می‌کنید. حال به لیست ایمیل‌های دریافتی بازگردید، آیا رفت و برگشتی به سرور انجام می‌شود؟ مسلما خیر. حتی اگر دوباره بر روی آن ایمیل مشاهده شده ، کلیک کنید، بدون رفت و برگشتی به سرور آن ایمیل را مشاهده می‌کنید.
کش شدن اطلاعات سبب می‌شود که بار سرور خیلی کاهش یابد و رفت و آمدهای بیهوده صورت نگیرد. کش شدن داده‌ها یک مزیت دیگر نیز دارد و آن تبدیل برنامه‌های معمول وب stateless به برنامه‌های شبه دسکتاپ state full است. 
  
تکنیک AJAX در پیاده سازی امکانات فوق نقشی اساسی را بازی می‌کند. کمی به عقب برمیگردیم یعنی زمانی که AJAX برای اولین بار مطرح شد و هدف اصلی به وجود آمدن آن پیاده سازی برنامه‌های وب به شکل دسکتاپ بود و این کار از طریق انجام تمامی ارتباطات سرور با  XMLHttpRequest  امکان پذیر می‌شد. شاید آن زمان با توجه به محدودیت تکنولوژی‌ها موجود این کار به صورت تمام و کمال امکان پذیر نبود، اما امروزه به بهترین شکل ممکن قابل پیاده سازی است.

 شاید اکنون این سوال پیش بیاید که چرا باید وبسایت خود را به شکل SPA طراحی کنیم؟
برای پاسخ دادن به این سوال باید گفت که سیستم‌های وب  امروزی به دو دسته‌ی زیر تقسیم می‌شوند:
Web Documents و یا همان وب سایت‌های معمول
Web Applications و یا همان Single Page Web Applications
اگر هدف شما طراحی یک وب سایت معمول است که هدف آن، نمایش یک سری اطلاعات است و به قولی دارای محتواست، مطمئنا پیاده سازی این سیستم به صورت SPA کاری بیهوده به نظر می‌آید؛ ولی اگر هدفتان نوشتن سیستم هایی مثل Gmail، Google Maps، Azure، Facebook و ... است، پیاده سازی آن‌ها به صورت وب سایت‌های معمولی، غیر معقول به نظر می‌آید. حتی بخش‌های مدیریتی یک وبسایت هم می‌تواند به خوبی توسط SPA پیاده سازی شود، چرا که واقعا برای مدیریت اطلاعات یک وب سایت احتیاجی نیست، که  از این صفحه به آن صفحه جا به جا شد.

معرفی کتابخانه‌ی AngularJS
AngularJS فریم ورکی متن باز و نوشته شده به زبان جاوا اسکریپت است. هدف از به وجود آمدن این فریم ورک، توسعه هر چه ساده‌تر SPA‌ها با الگوی طراحی MVC و تست پذیری هر چه آسان‌تر آن‌ها است. این فریم ورک توسط یکی از محققان Google در سال 2009 به وجود آمد. بعد‌ها این فریم ورک تحت مجوز MIT به صورت متن باز در آمد و اکنون گوگل آن را حمایت می‌کند و توسط هزاران توسعه دهنده در سرتاسر دنیا، توسعه داده می‌شود.
قبل از اینکه به بررسی ویژگی‌های Angular بپردازم، بهتر است ابتدا مطلبی درباره‌ی به کارگیری Angular از Brad Green که کارمند گوگل است، بیان کنم.
در سال 2009 تیمی در گوگل مشغول انجام پروژه ای به نام Google Feedback بودند. آن‌ها سعی داشتند تا در طی چند ماه، به سرعت کد‌های خوب و تست پذیر بنویسند. پس از 6 ماه کدنویسی، نتیجه‌ی کار 17000 خط کد شد. در آن موقع یکی از اعضای تیم به نام Misko Hevery، ادعا کرد که می‌تواند کل این پروژه را در دو هفته به کمک کتابخانه‌ی متن بازی که در اوقات فراغت توسعه داده است، بازنویسی کند. Misko نتوانست در دو هفته این کار را انجام دهد. اما پس از سه هفته همه‌ی اعضای تیم را شگفت زده کرد. نتیجه‌ی کار تنها 1500 خط بود! همین باعث شد که ما بفهمیم که، Misko بر روی چیزی کاری میکند که ارزش دنبال کردن دارد.
پس از آن قضیه Misko و Brad بر روی Angular کار کردند و اکنون هم Angular توسط تیمی در گوگل و هزاران توسعه دهنده‌ی متن باز حرفه ای در سرتاسر جهان، درحال توسعه است.
فکر کنم همین داستان ذکر شده، قدرت فوق العاده زیاد این فریم ورک را برای همگان آشکار سازد.

ویژگی‌های AngularJS:

قالب‌های سمت کاربر (Client Side Templates): انگولار دارای یک template engine قدرتمند برای تعریف قالب است.

پیروی از الگوی طراحی MVC: انگولار، الگوی طراحی MVC را برای توسعه پیشنهاد می‌دهد و امکانات زیادی برای توسعه هر چه راحت‌تر با این الگو فراهم کرده است.

Data Binding: امکان تعریف انقیاد داده دوطرفه (Two-Way Data Binding) در این فریم ورک به راحتی هرچه تمام، امکان پذیر است.

Dependency Injection: این فریم ورک برای دریافت وابستگی‌های تعریف شده، دارای یک سیستم تزریق وابستگی توکار است.

تعریف Service‌های سفارشی: در این فریم ورک امکان تعریف سرویس‌های دلخواه به صورت ماژول وجود دارد. این ماژول‌های مجزا را به کمک سیستم تزریق وابستگی توکار Angular، به راحتی در هر جای برنامه می‌توان تزریق کرد.

تعریف Directive‌های سفارشی: یکی از جذاب‌ترین و قدرتمند‌ترین امکانات این فریم ورک، تعریف Directive‌های سفارشی است.  Directive ها، امکان توسعه HTML را فراهم کرده اند. توسعه‌ی HTML اکنون در قالب Web Components‌ها فراهم شده است، اما هنوز هم خیلی از مرورگر‌های جدید نیز از آن پشتیبانی نمی‌کنند.

فرمت کردن اطلاعات با استفاده از فیلترهای سفارشی: با استفاده از فیلترها میتوانید چگونگی الحاق شدن اطلاعات را برای نمایش به کاربر تایین کنید ؛ انگولار همراه با فیلترهای گوناگون مختلفی عرضه میشود که میتوان برایه مثال به فیلتر currency ، date ،uppercase کردن رشته‌ها و .... اشاره کرد همچنین شما محدود به فیلترهای تعریف شده در انگولار نیستید و آزادید که فیلترهای سفارشی خودتان را نیز تعریف کنید.

سیستم Routing: دارا بودن سیستم Routing  قدرتمند، توسعه SPA‌ها را بسیار ساده کرده است.

سیستم اعتبار سنجی: Angular دارای سیستم اعتبار سنجی توکار قدرتمند برای بررسی داده‌های ورودی است.

سرویس تو کار برای ارتباط با سرور: Angular دارای سرویس پیش فرض ارتباط با سرور به صورت AJAX است.

تست پذیری: Angular دارای بستری آماده برای تست کردن برنامه‌های نوشته شده است و از Unit Tests و Integrated End-to-End Test هم پشتیبانی می‌کند.

جامعه‌ی متن باز بسیار قوی
   
این‌ها فقط یک مرور کلی بر توانایی‌های این فریم ورک بود و در ادامه هر کدام از این ویژگی را به صورت دقیق بررسی خواهیم کرد.
در مقاله‌ی بعدی، به چگونگی نصب AngularJS خواهیم پرداخت. سپس، اولین کد خود را با استفاده از آن خواهیم نوشت و مطالب Client Side Templates و MVC را دقیق‌تر بررسی خواهیم کرد.
 
نظرات مطالب
شروع به کار با AngularJS 2.0 و TypeScript - قسمت اول - نصب پیشنیازها
- شاید Angular 2 بهترین نباشد یا نشود، اما این مهم نیست. عوامل زیادی در انتخاب یک فریم ورک مؤثر هستند:

  • چه کسانی این فریم ورک را توسعه می‌دهند؟ گوگل. این مورد خیلی مهم است. در این بین شاید Aurelia مدرن‌تر به نظر برسد اما تیم آن سابقه‌ی خوبی در نگهداری محصولات قبلی آن ندارد. برای مثال Durandal آن‌ها به طور کامل رها شده و الان Aurelia را شروع کرده‌اند.
  • تیم Angular اینقدر شجاعت داشته که اقرار کند نگارش 1 آن مشکلات زیادی دارد و دست به یک بازنویسی کامل زده‌اند. باید دقت کرد که چقدر این‌کار برای یک تیم محبوب در وب مشکل است و قطعا نگارش 2 آن که با این حجم بالای اعتراضات عدم سازگاری با نگارش 1 آن تولید شده‌است، بسیاری از مشکلات نگارش قبلی را ندارد. همچنین همین مساله سازگاری آن‌را با نگارش‌های بعد از 2 نیز تضمین خواهد کرد. چون اینبار دست به یک طراحی مجدد زده‌اند و ... این طراحی مجدد خیلی برای آن‌ها گران تمام شده‌است (خصوصا از لحاظ حجم انتقادهای رسیده). بنابراین در آینده در زمینه سازگاری با نگارش‌های قبلی به شدت محتاط خواهند بود. این موردی است که استفاده کنندگان از ReactJS به زودی با آن مواجه خواهند شد.
  • گروه کاربری مصرف کنندگان آن. چه تعداد مقاله، ویدیوی آموزشی، انجمن رفع اشکال و امثال این‌ها را در مورد یک محصول می‌توانید پیدا کنید؟ قطعا AngularJS در این زمینه حرف اول را می‌زند.
  • Angular 2 بر مبنای استاندارد web component طراحی شده‌است که در دراز مدت نیز سبب برد AngularJS 2 خواهد شد و نیاز کمتر به بازنویسی‌های کلی.
  • Angular 2 برای کار با محصولات موبایل بهینه سازی شده‌است و مانند بوت استرپ 3 یک فریم ورک mobile first است.
  • استفاده‌ی از Type Script به عنوان زبان اول این پلتفرم (البته استفاده‌ی از آن اجباری نیست). این مساله در دراز مدت سبب تولید کدهایی با کیفیت بالاتر می‌شود. برای مثال الان ReactJS مخلوطی است از ES 5 و ES 6. اما AngularJS 2 تصمیم بهتری را اتخاذ کرده‌است. همین مساله سبب شده‌است که توسعه‌ی Type Script توسط مایکروسافت سرعت بیشتری پیدا کند.
  • داشتن امکانات توکار بیشتری نسبت به رقبا. برای مثال ReactJS یک کتابخانه است؛ اما AngularJS 2 یک فریم ورک کامل که تمام کتابخانه‌های جانبی رقبا را یکجا از روز اول دارد.

بنابراین آیا پس از ارائه‌ی نهایی Angular 2، ارزش یادگیری را دارد؟ بله؛ حتما. ابتدا (و هم اکنون) اعتراض‌های شدیدی در مورد عدم سازگاری آن با نگارش‌های قبلی وجود خواهد داشت و پس از مدتی همه آن‌را فراموش کرده و خودشان را وفق می‌دهند.  
نظرات مطالب
بررسی مشکلات AngularJS 1.x
بنده قصد خراب کردن این فریمورک را نداشتم. اشکالات بیان شده همگی مربوط به مقالاتی هستند که توسعه دهندگان به اشتراک گذاشتند. من هم آن‌ها را تایید نکردم ولی وقتی می‌بینید که angular 2 همان اشکالات وارد شده به نسخه 1 را برطرف کرده است می‌توان نتیجه  گرفت که اشکالات نسخه 1 صحیح بوده اند و باید اصلاح می‌شدند.
بنده هم نگفتم که انگولار را یاد نگیرید، گفتم "حداقل یادگیری آن را تا انتشار نسخه‌ی 2 آن به تعویق بیندازید."
نکته بحث "الان" هست نه گذشته. الان که قرار هست نسخه‌ی 2 منتشر شه و تغییرات زیادی داره چه دلیلی داره پروژه جدیدی را با آن شروع کنیم و بعد شروع به تغییر کدهایمان کنیم.
بله راهنمایی برای مهاجرت از نسخه‌ی 1 به نسخه 2 وجود دارد: 
اگر با این روش با آپگرید پروژتون که ممکن است چند هزار خط داشته باشد مشکلی ندارید، معطل نکنید همین امروز پروژه جدیدتون را با انگولار آغاز کنید.
باز هم نمی‌گویم انگولار بد است، همین الان میشود مقاله ای برای مزیت‌های نوشت. فقط قصدم این بود که به هنگام استفاده از انگولار و توسعه spa این موارد را هم در نظر داشته باشید.


نظرات مطالب
شروع به کار با AngularJS 2.0 و TypeScript - قسمت نهم - مسیریابی
به روز رسانی

تمام مسیریابی‌های  این سری به نگارش سوم روتر AngularJS 2.0 به روز رسانی شدند.
ریز جزئیات تغییرات

توضیحات:

ابتدا نیاز است وابستگی‌های روتر جدید را به نحو ذیل به فایل package.json اضافه کنید:
 "dependencies": {
    // ...
    "@angular/router": "^3.0.0-alpha.7",
    // ...  
},
سپس
یک فایل جدید را به نام app.routes.ts به ریشه‌ی پروژه اضافه کنید، با این محتوا
import { provideRouter, RouterConfig } from '@angular/router';

import { ProductListComponent } from './products/product-list.component';
import { WelcomeComponent } from './home/welcome.component';
import { ProductDetailComponent } from './products/product-detail.component';
import { ProductFormComponent }  from './products/product-form.component';
import { SignupFormComponent } from './users/signup-form.component';
import { TypedShaComponent } from './using-third-party-libraries/typed-sha.component';
import { UnTypedShaComponent } from './using-third-party-libraries/untyped-sha.component';
import { UsingJQueryAddonsComponent } from './using-jquery-addons/using-jquery-addons.component';

export const routes: RouterConfig = [
    { path: '', component: WelcomeComponent },
    { path: 'welcome', component: WelcomeComponent },
    { path: 'products', component: ProductListComponent },
    { path: 'product/:id', component: ProductDetailComponent },
    { path: 'addproduct', component: ProductFormComponent },
    { path: 'adduser', component: SignupFormComponent },
    { path: 'typedsha', component: TypedShaComponent },
    { path: 'untypedsha', component: UnTypedShaComponent },
    { path: 'usingjquery', component: UsingJQueryAddonsComponent }
];

export const APP_ROUTER_PROVIDERS = [
  provideRouter(routes)
];
در اینجا مسیریابی‌های قدیمی برنامه از فایل app.component.ts خارج شده و به یک فایل مستقل منتقل شده‌اند.
در سیستم مسیریابی جدید، خاصیت‌های name و useAsDefault وجود ندارند و حذف شده‌اند. همچنین مسیریابی‌ها نباید با / شروع شوند.
به علاوه در فایل index.html، مسیر ریشه به نحو ذیل مشخص می‌شود:
 <base href=".">
پس از تعریف فایل app.routes.ts، نیاز است آن‌را به main.ts معرفی کرد:
 // ...
import { APP_ROUTER_PROVIDERS } from './app.routes';
// ...
bootstrap(AppComponent, [
   // ...
   APP_ROUTER_PROVIDERS
])
.catch(err => console.error(err));
به این ترتیب کار برپایی مسیریابی اصلی سایت به پایان می‌رسد.
البته باید دقت داشت که فایل systemjs.config.js هم کمی نیاز است جهت بارگذاری این مسیریاب جدید اصلاح شود.

در ادامه، در فایل app.component.ts، دایرکتیوهای مرتبط با مسیریابی که در ROUTER_DIRECTIVES قرار دارند، اینبار از ماژول ذیل تامین می‌شوند:
 import { ROUTER_DIRECTIVES } from '@angular/router';

سپس لینک‌های مسیریابی، اینبار بجای نام مسیریابی که در نگارش سوم روتر، حذف شده‌است، به همان مسیر متناظر اشاره می‌کند:
 <a [routerLink]="['/welcome']">Home</a>
این مورد جهت متدهای navigate هم صدق می‌کند و بجای نام، به مسیر مدنظر باید ویرایش شوند:
 this._router.navigate(['/products']);
تغییر مهم دیگر رخ داده، در مورد نحوه‌ی دسترسی به پارامترهای مسیریابی است که نمونه‌ای از آن‌را در مورد product-detail.component.ts در اینجا مشاهده می‌کنید:
import { Component, OnInit, OnDestroy } from '@angular/core';
import { Router, ActivatedRoute } from '@angular/router';

@Component({
    templateUrl: 'app/products/product-detail.component.html'
    //template: require('./product-detail.component.html')//for webpack
})
export class ProductDetailComponent implements OnInit, OnDestroy {
    private sub: any;
    pageTitle: string = 'Product Detail';
    constructor(private _route: ActivatedRoute, private _router: Router) {
    }

    ngOnInit(): void {
        this.sub = this._route.params
            .subscribe(params => {
                let id = +params['id']; // (+) converts string 'id' to a number
                this.pageTitle += `: ${id}`;
            });
    }

    ngOnDestroy(): void {
        this.sub.unsubscribe(); // we must unsubscribe before Angular destroys the component. Failure to do so could create a memory leak.
    }

    onBack(): void {
        this._router.navigate(['/products']);
    }
}
اینبار سرویس RouteParams حذف شده‌است و بجای آن ActivatedRoute را داریم که خاصیت params آن، یک observable را باز می‌گرداند. به همین جهت باید متد subscribe آن‌را جهت دسترسی به پارامترهای مسیریابی، فراخوانی کرد. این فراخوانی نیز باید در متد ngOnInit باشد و همچنین برای جلوگیری از نشتی حافظه، باید در ngOnDestroy کار unsubscribe آن انجام شود.

یک اصلاح دیگر هم در اینجا داریم. لینک به صفحه‌ی جزئیات هر محصول اینبار به صورت زیر ویرایش می‌شود (در فایل product-list.component.html):
 <a [routerLink]="['/product', product.productId]">
  {{product.productName}}
</a>