نظرات مطالب
React 16x - قسمت 1 - معرفی و شروع به کار
اگر نسخه Node >= 8.10  و  npm >= 5.6 را نصب دارید. با دستور زیر میتوان پروژه ای ایجاد نمود:
npx create-react-app my-app
cd my-app
npm start
ابزار npx  یک package runner می باشد که از نسخه npm 5.2 به بعد در دسترس می‌باشد. 
مطالب
آموزش فریم ورک Vuetify قسمت اول - نصب و بررسی ساختار grid؛ بخش دوم
در بخش قبل با نصب فریم ورک vuetify و بخشی از کامپوننت‌های آن آشنا شدیم .

Order :

به‌وسیله‌ی order میتوان ترتیب قرارگیری آیتمهای Grid را مشخص کرد. فرض کنید یک ردیف سه ستون داریم و می‌خواهیم زمانیکه این آیتمها در مروگر نمایش داده می‌شوند، ترتیب قرارگیری آنها متناسب با نیاز ما باشد که با استفاده از دستور order این کار صورت می‌پذیرد. 

نکته: این کار برای بحث seo مورد استفاده قرار میگیرد.

 در پایین با یک مثال، چگونگی انجام اینکار شرح داده شده‌است: 
در توضیح کد پایین اینگونه میتوان گفت که درون کامپوننت <v-layout>، در خط چهارم برنامه، سه کامپوننت <v-flex> قرار داده شده‌اند که به وسیله order، ترتیب نمایش آنها را مشخص کرده‌ایم . در <v-flex> اول order با مقدار md2 مشخص شده‌است. بدین معنا که محتویات این <v-flex>، درون خانه دوم نمایش داده شود و به همین ترتیب برای <v-flex>‌های بعدی نیز این مقادیر تنظیم شده‌اند.
<div id="app">
  <v-app id="inspire">
    <v-container fluid>
              <v-flex xs4 order-md2>
          <v-card dark tile flat color="red lighten-1">
            <v-card-text>#1</v-card-text>
          </v-card>
        </v-flex>
        <v-flex xs4 order-md3>
          <v-card dark tile flat color="red lighten-2">
            <v-card-text>#2</v-card-text>
          </v-card>
        </v-flex>
        <v-flex xs4 order-md1>
          <v-card dark tile flat color="red darken-1">
            <v-card-text>#3</v-card-text>
          </v-card>
        </v-flex>
      </v-layout>
      <v-layout row wrap>
        <v-flex xs12 sm6 md3 order-md4 order-sm2>
          <v-card dark tile flat color="red darken-2">
            <v-card-text>#1</v-card-text>
          </v-card>
        </v-flex>
        <v-flex xs12 sm6 md3 order-md3 order-sm1>
          <v-card dark tile flat color="deep-orange lighten-1">
            <v-card-text>#2</v-card-text>
          </v-card>
        </v-flex>
        <v-flex xs12 sm6 md3 order-md2 order-sm4>
          <v-card dark tile flat color="deep-orange darken-3">
            <v-card-text>#3</v-card-text>
          </v-card>
        </v-flex>
        <v-flex xs12 sm6 md3 order-md1 order-sm3>
          <v-card dark tile flat color="deep-orange">
            <v-card-text>#4</v-card-text>
          </v-card>
        </v-flex>
      </v-layout>
    </v-container>
  </v-app>
</div>
نتیجعه قطعه کد بالا به این صورت است.


Direction & Align :
به وسیله تنظیم مقادیر Direction & align برای کامپوننت <v-flex> می‌توان برای ایجاد فواصل بین سطرها و ستون‌ها و همچنین نحوه چینش آنها استفاده کرد. اگر به قطعه کد زیر توجه داشته باشید، این تنظیمات شامل justify-space-between , justify-space-around , justify-center هستند که عملکرد هر کدام به صورت جداگانه نمایش داده شده است.
<div id="app">
  <v-app id="inspire">
    <v-container fluid grid-list-xl>
      <v-layout row justify-space-between>
        <v-flex xs2>
          <v-card dark color="primary">
            <v-card-text>one</v-card-text>
          </v-card>
        </v-flex>
        <v-flex xs2>
          <v-card dark color="secondary">
            <v-card-text>two</v-card-text>
          </v-card>
        </v-flex>
        <v-flex xs2>
          <v-card dark color="accent">
            <v-card-text>three</v-card-text>
          </v-card>
        </v-flex>
      </v-layout>
      <v-layout row justify-space-around>
        <v-flex xs2>
          <v-card dark color="primary">
            <v-card-text>one</v-card-text>
          </v-card>
        </v-flex>
        <v-flex xs2>
          <v-card dark color="secondary">
            <v-card-text>two</v-card-text>
          </v-card>
        </v-flex>
        <v-flex xs2>
          <v-card dark color="accent">
            <v-card-text>three</v-card-text>
          </v-card>
        </v-flex>
      </v-layout>
      <v-layout row justify-center>
        <v-flex xs2>
          <v-card dark color="primary">
            <v-card-text>one</v-card-text>
          </v-card>
        </v-flex>
        <v-flex xs2>
          <v-card dark color="secondary">
            <v-card-text>two</v-card-text>
          </v-card>
        </v-flex>
        <v-flex xs2>
          <v-card dark color="accent">
            <v-card-text>three</v-card-text>
          </v-card>
        </v-flex>
      </v-layout>
    </v-container>
  </v-app>
</div>
نتیجه قطعه کد بالا بدین ترتیب است :


Grow & Shrink :
در لغت، Grow به معنی رشد و توسعه دادن و Shrink به معنی کوچک کردن می‌باشد که در اینجا نیز دقیقا همین عملکرد را دنبال می‌کنند. هرگاه برای یک کامپوننت <v-flex>  مقدار Grow را تنظیم نماییم، آن <v-flex> تمامی قسمت خالی عرض صفحه را به خود اختصاص می‌دهد. اما اگر برای کامپوننت <v-flex> مقدار Shrink را تنظیم نماییم، به میزان محتویات درونی خود جا اشغال می‌نماید.
نکته: pa-1 در اینجا به معنی padding می‌باشد که به وسیله pa-1 در چهار جهت بالا، پایین، چپ و راست، padding اعمال می‌شود.
<div id="app">
  <v-app id="inspire">
    <v-container fluid>
      <v-layout row>
        <v-flex grow pa-1>
          <v-card dark color="green darken-3">
            <v-card-text>#1 Im a Grow Flex</v-card-text>
          </v-card>
        </v-flex>
        <v-flex shrink pa-1>
          <v-card dark color="green darken-1">
            <v-card-text>#2 Im a Shrink Flex</v-card-text>
          </v-card>
        </v-flex>
      </v-layout>
      <v-layout row>
        <v-flex grow pa-1>
          <v-card dark color="green darken-1">
            <v-card-text>#1 Im a Grow Flex</v-card-text>
          </v-card>
        </v-flex>
        <v-flex shrink pa-1>
          <v-card dark color="green lighten-1">
            <v-card-text>#2 Im a Shrink Flex</v-card-text>
          </v-card>
        </v-flex>
        <v-flex grow pa-1>
          <v-card dark color="green darken-4">
            <v-card-text>#3 Im a Grow Flex</v-card-text>
          </v-card>
        </v-flex>
      </v-layout>
      <v-layout row>
        <v-flex shrink pa-1>
          <v-card dark color="green darken-3">
            <v-card-text>#1 Im a Shrink Flex</v-card-text>
          </v-card>
        </v-flex>
        <v-flex grow pa-1>
          <v-card dark color="green">
            <v-card-text>#2 Im a Grow Flex</v-card-text>
          </v-card>
        </v-flex>
        <v-flex shrink pa-1>
          <v-card dark color="green lighten-1">
            <v-card-text>#3 Im a Shrink Flex</v-card-text>
          </v-card>
        </v-flex>
      </v-layout>
    </v-container>
  </v-app>
</div>
نتیجه قطعه کد بالا:


Nested grid :
در این فریم ورک قابلیت تعریف nested grid همانند سایر CSS فریم ورک‌ها مقدور است. nested grid‌ها در واقع ردیف‌هایی هستند که درون ستون‌ها قرار میگیرند. بدین وسیله  می‌توان هر ستون را به 12 قسمت، تقسیم بندی کرد.
<div id="app">
  <v-app id="inspire">
    <v-container fluid grid-list-md>
      <v-layout row wrap>
        <v-flex d-flex xs12 sm6 md4>
          <v-card color="purple" dark>
            <v-card-title primary>Lorem</v-card-title>
            <v-card-text>{{ lorem }}</v-card-text>
          </v-card>
        </v-flex>
        <v-flex d-flex xs12 sm6 md3>
          <v-layout row wrap>
            <v-flex d-flex>
              <v-card color="indigo" dark>
                <v-card-text>{{ lorem.slice(0, 70) }}</v-card-text>
              </v-card>
            </v-flex>
            <v-flex d-flex>
              <v-layout row wrap>
                <v-flex v-for="n in 2":key="n" d-flex xs12
                >
                  <v-card
                    color="red lighten-2"
                    dark
                  >
                    <v-card-text>{{ lorem.slice(0, 40) }}</v-card-text>
                  </v-card>
                </v-flex>
              </v-layout>
            </v-flex>
          </v-layout>
        </v-flex>
        <v-flex d-flex xs12 sm6 md2 child-flex>
          <v-card color="green lighten-2" dark>
            <v-card-text>{{ lorem.slice(0, 90) }}</v-card-text>
          </v-card>
        </v-flex>
        <v-flex d-flex xs12 sm6 md3>
          <v-card color="blue lighten-2" dark>
            <v-card-text>{{ lorem.slice(0, 100) }}</v-card-text>
          </v-card>
        </v-flex>
      </v-layout>
    </v-container>
  </v-app>
</div>
نتیجه قطعه کد بالا :



نظرات مطالب
Angular Material 6x - قسمت هفتم - کار با انواع قالب‌ها
سلام
راهی وجود داره که اندازه کنترل‌های متریال به صورت یکدست کوچکتر بشه ؟ متریال ظاهر زیبایی داره ولی کنترل هاش خیلی درشت و بزرگ و با فاصله هستند نسبت به بوت استرپ یا PrimeNG از اندازه خیلی بزرگتری برخوردارند.
مطالب
بررسی برخی تغییرات در Angular 8
تغییر loadChildren در نسخه 8
در نسخه 8، استفاده از syntax رشته‌ای برای loadChildren  در lazy loading، منسوخ شده‌است:
const routes: Routes = [{
  path: 'lazy',
  // The following string syntax for loadChildren is deprecated
  loadChildren: './lazy/lazy.module#LazyModule'
}];
و بجای آن  از syntax جدید `()import` استفاده می‌شود:
const routes: Routes = [{
  path: 'lazy',
  // The new import() syntax
  loadChildren: () => import('./lazy/lazy.module').then(m => m.LazyModule)
}];
در زمان بروزرسانی به نسخه 8، دستور ng update، عمل تبدیل مسیرهای loadChildren به syntax جدید را به طور خودکار انجام می‌دهد.

import مجزای component‌‌های Material
اگر ازAngular Material استفاده می‌کنید باید Component ‌های مورد استفاده را بطور مجزا import کنید. به عنوان مثال اگر از button استفاده کرده‌اید، باید @angular/material/button را import  کنید . البته در اینجا نیز دستور ng update این کار را بطور خودکار انجام می‌دهد.

بهبود CLI با تولید بسته‌های متفاوت ES 5 و ES 6
در نسخه 8، دستور build ارائه شده توسط CLI می‌تواند دو خروجی متفاوت با  ES2015 مخصوص مرورگرهای جدید را با حداقل polyfills و ES5 سازگار با مرورگرهای قدیمی را بدهد. در صورتی که بخواهیم build سازگاری با نسخه‌های  قدیمی داشته باشیم، می‌توانیم گزینه target در فایل tsconfig.json را به ES5 تغییر دهیم. 
برای بروزرسانی پروژه‌های جاری خود می‌توانید از ابزار کمکی ارائه شده توسط تیم angular استفاده کنید. 
 
روش فعالسازی کامپایلر جدید Angular
برای ساخت پروژه‌ای با قابلیت استفاده از ivy compiler می‌توانیم از دستور زیر استفاده کنیم:
ng new angularProjectName --enable-ivy
توجه داشته باشید نیاز است nodejs نسخه 10.9 یا 10.9 به بعد نصب باشد. 
پس از ساخت پروژه قسمتی با نام angularCompilerOptions  در فایل tsconfig.json مشاهد می‌شودکه نشان دهنده‌ی فعال بودن کامپایلر ivy است:
"angularCompilerOptions": {
    "enableIvy": true
  }
مطالب
AngularJS #4
در این قسمت قصد دارم تا یک سیستم ارسال دیدگاه را به کمک Angular پیاده سازی کنم. هدف از این مثال؛ آشنایی با چند Directive توکار Angular و همچنین آموختن چگونگی کار با سرویس http$ برای ارتباط با سرور است.
کدهای HTML زیر را در نظر بگیرید:
<div ng-app="myApp">
    <div ng-controller="CommentCtrl">

        <div ng-repeat="comment in comments">
            <div style="float:right;cursor:pointer;" ng-click="remove(comment.Id,$index);">X</div>
            <a href="#">
                <img style="width:32px;" ng-src="/Content/user.gif" alt="{{comment.Name}}">
            </a>
            <div>
                <h4>{{comment.Name}}</h4>
                {{comment.CommentBody}}
            </div>
        </div>

        <div>
            <form action="/Comment/Add" method="post">
                <div>
                    <label for="Name">Name</label>
                    <input id="Name" type="text" name="Name" ng-model="comment.Name" placeholder="Your Name" />
                </div>
                <div>
                    <label for="Email">Email</label>
                    <input id="Email" type="text" name="Email" ng-model="comment.Email" placeholder="Your Email" />
                </div>
                <div>
                    <label for="CommentBody">Comment</label>
                    <textarea id="CommentBody" name="CommentBody" ng-model="comment.CommentBody" placeholder="Your Comment"></textarea>
                </div>
                <button type="button" ng-click="addComment()">Send</button>
            </form>
        </div>

    </div>
</div>
خب از ابتدا ساختار را مورد بررسی قرار می‌دهم و موارد ناآشنای آن را توضیح می‌دهم:

ng-app: خاصیت ng-app جز خواص پیش فرض HTML نیست و یک خاصیت سفارشی است که توسط Angular به صورت پیش فرض تعریف شده است. این خاصیت به Angular می‌گوید که کدام بخش از DOM باید توسط Angular مدیریت و پردازش شود. در اینجا div ای که با خاصیت ng-app مزین شده است به همراه تمامی عناصر فرزند آن توسط موتور پردازش گر DOM توکار مورد پردازش قرار گرفته و اصطلاحا کامپایل می‌شود. بله! اینجا از لفظ کامپایل شدن برای بیان این فرآیند استفاده کردم. هیچ کدام از این Directive‌های سفارشی به خودی خود برای مرورگر قابل تفسیر نیست و اینجاست که Angular وارد عمل شده و این Directive‌ها را به کدهای HTML و جاوا اسکریپت که برای مرورگر قابل فهم است تبدیل می‌کند. به همین جهت با ng-app مشخص می‌کنیم که کدام بخش از DOM باید توسط Angular تفسیر و مدیریت شود.شاید این سوال برای شما مطرح شده باشد که در مثال قبلی ng-app مقداری نداشت و برای تگ html تعریف شده بود. پاسخ این است که در مثال قبلی چون برنامه‌ی ما دارای یک ماژول بیشتر نبود می‌توانستیم از مقدار دهی ng-app صرف نظر کنیم؛ اما در این مثال ما قصد داریم کمی هم مفهوم ماژول را در Angular بررسی کنیم. در نتیجه در این مثال برنامه‌ی ما از ماژولی به نام myApp تشکیل شده است. دلیل اینکه در این مثال ng-app بر روی یک div تعریف شده است این است که همین قسمت از DOM توسط Angular تفسیر شود برای ما کفایت می‌کند. هنگامی ng-app را بر روی html تعریف می‌کنیم که قصد داشته باشیم کل صفحه توسط Angular تفسیر شود.
 
ng-controller: در Angular کنترلر‌ها تابع سازنده‌ی کلاس‌های ساده‌ی جاوا اسکریپتی هستند که به کمک آن‌ها بخشی از صفحه را مدیریت می‌کنیم. این که کدام بخش از صفحه توسط کدام کلاس کنترل و مدیریت شود، توسط ng-controller مشخص می‌شود. در اینجا هم عنصری که با ng-controller مشخص شده به همراه تمامی فرزندانش، توسط کلاس جاوا اسکریپتی به نام CommentCtrl مدیریت می‌شود. در حقیقت ما به کمک ng-controller مشخص می‌کنیم که کدام قسمت از View توسط کدام Controller مدیریت می‌شود. مرسوم است که در Angular نام کنترلرها با Ctrl خاتمه یابد.
   
ng-repeat: همه‌ی نظرات دارای یک قالب html یکسان هستند که به ازای داده‌های متفاوت تکرار شده اند. اگر می‌خواستیم نظرات را استفاده از موتور نمایشی Razor نشان دهیم از یک حلقه‌ی foreach استفاده می‌کردیم. خبر خوب این است که ng-repeat هم دقیقا به مانند حلقه‌ی foreach عمل می‌کند.در اینجا عبارت comment in comments دقیقا برابر با آن چیزی است که در یک حلقه‌ی foreach می‌نوشتیم. Comments در اینجا یک لیست به مانند آرایه ای از comment هست که در کنترلر مقدار دهی شده است. پس اگر با حلقه‌ی foreach مشکلی نداشته باشید با مفهوم ng-repeat هم مشکلی نخواهید داشت و دقیقا به همان شکل عمل می‌نماید.
     
ng-click: همان طور که گفتیم Directive‌های تعریف شده می‌توانند یک event سفارشی نیز باشند. ng-click هم یک Directive تو کار است که توسط Angular به صورت پیش فرض تعریف شده است. کاملا مشخص است که یک تابع به نام remove تعریف شده است که به هنگام کلیک شدن، فراخوانی می‌شود. دو پارامتر هم به آن ارسال شده است. اولین پارامتر Id دیدگاه مورد نظر است تا به سرور ارسال شود و از پایگاه داده حذف شود. دومین پارامتر index$ است که یک متغیر ویژه است که توسط Angular در هر بار اجرای حلقه‌ی ng-repeat مقدارش یک واحد افزایش می‌یابد. index$ هم به تابع remove ارسال می‌شود تا بتوان فهمید در سمت کلاینت کدام نظر باید حذف شود.
 
ng-src: از این Directive برای مشخص کردن src عکس‌ها استفاده می‌شود. البته در این مثال چندان تفاوتی بین ng-src و src معمولی وجود ندارد. ولی اگر آدرس عکس به صورت Content/{{comment.Name}}.gif می‌بود دیگر وضع فرق می‌کرد. چرا که مرورگر با دیدن آدرس در src سعی به لود کردن آن عکس می‌کند و در این حالت در لود کردن آن عکس با شکست روبرو می‌شود. ng-src سبب می‌شود تا در ابتدا آدرس عکس توسط Angular تفسیر شود و سپس آن عکس توسط مرورگر لود شود.
   
{{comment.Name}}: آکلودهای دوتایی برای انقیاد داده (Data Binding) با view-model استفاده می‌شود. این نوع اقیاد داده در مثال‌های قبلی مورد بررسی قرار گرفته است و نکته‌ی بیشتری در اینجا مطرح نیست.
   
ng-model: به کمک ng-model می‌توان بین متن داخل textbox و خاصیت شی مورد نظر انقیاد داده بر قرار کرد و هر دو طرف از تغییرات یکدیگر آگاه شوند. به این عمل انقیاد داده دوطرفه (Two-Way Data-Binding) می‌گویند.برای مثال textbox مربوط به نام را به comment.Name و textbox مربوط به email را به comment.Email مقید(bind) شده است. هر تغییری که در محتوای هر کدام از طرفین صورت گیرد دیگری نیز از آن تغییر با خبر شده و آن را نمایش می‌دهد.
   
تا به اینجای کار قالب مربوط به HTML را بررسی کردیم. حال به سراغ کدهای جاوا اسکریپت می‌رویم:
var app = angular.module('myApp', []);

app.controller('CommentCtrl', function ($scope, $http) {

    $scope.comment = {};

    $http.get('/Comment/GetAll').success(function (data) {

        $scope.comments = data;

    })

    $scope.addComment = function () {

        $http.post("/Comment/Add", $scope.comment).success(function () {

            $scope.comments.push({ Name: $scope.comment.Name, CommentBody: $scope.comment.CommentBody });

            $scope.comment = {};

        });
    };

    $scope.remove = function (id, index) {

        $http.post("/Comment/Remove", { id: id }).success(function () {

            $scope.comments.splice(index, 1);

        });
    };

});
در تعریف ng-app اگر به یاد داشته باشید برای آن مقدار myApp در نظر گرفته شده بود. در اینجا هم ما به کمک متغیر سراسری angular که توسط خود کتابخانه تعریف شده است، ماژولی به نام myApp را تعریف کرده ایم. پارامتر دوم را فعلا توضیح نمی‌دهم، ولی در این حد بدانید که برای تعریف وابستگی‌های این ماژول استفاده می‌شود که من آن را برابر یک آرایه خالی قرار داده ام.
در سطر بعد برای ماژول تعریف شده یک controller تعریف کرده ام. شاید دفعه‌ی اول است که تعریف کنترلر به این شکل را مشاهده می‌کنید. اما چرا به این شکل کنترلر تعریف شده و به مانند قبل به شکل تابع سازنده‌ی کلاس تعریف نشده است؟
پاسخ این است که اکثر برنامه نویسان از جمله خودم دل خوشی از متغیر سراسری ندارند. در شکل قبلی تعریف کنترلر، کنترلر به شکل یک متغیر سراسری تعریف می‌شد. اما استفاده از ماژول برای تعریف کنترلر سبب می‌شود تا کنترلرهای ما روی هوا تعریف نشده باشند و هر یک در جای مناسب خود باشند. به این شکل مدیریت کدهای برنامه نیز ساده‌تر بود. مثلا اگر کسی از شما بپرسد که فلان کنترلر کجا تعریف شده است؛ به راحتی می‌گویید که در فلان ماژول برنامه تعریف و مدیریت شده است.
در تابعی که به عنوان کنترلر تعریف شده است، دو پارامتر به عنوان وابستگی درخواست شده است. scope که برای ارتباط با view-model و انقیاد داده به کار می‌رود و http$  که برای ارتباط با سرور به کار می‌رود. نمونه‌ی مناسب هر دوی این پارامترها توسط سیستم تزریق وابستگی تو کار angular در اختیار کنترلر قرار می‌گیرد.
قبلا چگونگی استفاده از scope$ برای اعمال انقیاد داده توضیح داده شده است. نکته‌ی جدیدی که مطرح است چگونگی استفاده از سرویس http$ برای ارتباط با سرور است. سرویس http $   دارای 4 متد put ، post ، get و delete است.
واقعا استفاده از این سرویس کاملا واضح و روشن است. در متد addComment وقتی که دیدگاه مورد نظر اضافه شد، به آرایه‌ی کامنت‌ها یک کامنت جدید می‌افزاییم و چون انقیاد داده دو طرفه است، بالافاصله دیدگاه جدید نیز در view به نمایش در می‌آید.کار تابع remove هم بسیار ساده است. با استفاده از index ارسالی، دیدگاه مورد نظر را از آرایه‌ی کامنت‌ها حذف می‌کنیم و ادامه‌ی کار توسط انقیاد داده دو طرفه انجام می‌شود.
همان طور که مشاهده می‌شود مفاهیم انقیاد داده دو طرفه و تزریق وابستگی خودکار سرویس‌های مورد نیاز، کار با angularjs را بسیار ساده و راحت کرده است. اصولا در بسیاری از موارد احتیاجی به باز اختراع چرخ نیست و کتابخانه‌ی angular آن را برای ما از قبل تدارک دیده است.
   
کدهای این مثال ضمیمه شده است. این کدها در Visual Studio 2013 و به کمک ASP.NET MVC 5 و Entity Framework 6 نوشته شده است. سعی شده تا مثال نوشته شده به واقعیت نزدیک باشد. اگر دقت کنید مدل کامنت در مثالی که نوشتم به گونه ای است که دیدگاه‌های چند سطحی به همراه پاسخ هایش مد نظر بوده است. به عنوان تمرین نمایش درختی این گونه دیدگاه‌ها را به کمک Angular انجام دهید. کافیست Treeview in Angular را جست و جو کنید؛ مطمئنا به نتایج زیادی می‌رسید. گرچه در مثال ضمیمه شده اگر جست و جو کنید من پیاده سازیش را انجام دادم. هدف از جست و جو در اینترنت مشاهده این است که بیشتر مسائل در Angular از پیش توسط دیگران حل شده است و احتیاجی نیست که شما با چالش‌های جدیدی دست و پنجه نرم کنید.
پس به عنوان تمرین، دیدگاه‌های چند سطحی به همراه پاسخ که نمونه اش را در همین سایتی که درحال مشاهده آن هستید می‌بینید را به کمک AngularJS پیاده سازی کنید.
  
در مقاله‌ی بعدی چگونگی انتقال منطق تجاری برنامه از کنترلر به لایه سرویس و چگونگی تعریف سرویس جدید را مورد بررسی قرار می‌دهم.
   

مطالب
شروع کار با Apache Cordova در ویژوال استودیو #5

همانطور که در قسمت قبل گفته شد، در این قسمت با روش کار jQuery Mobile و plugin‌های مربوط به Cordova آشنا خواهیم شد.


تگ متای زیر برای تنظیمات مربوط به viewport است و برای jQuery Mobile توصیه می‌شود.
<!DOCTYPE html> 
<html> 
<head> 
<meta charset="utf-8"> 
<title>Title</title> 
<meta name="viewport" content="width=device-width, initial-scale=1">
device-width  نشان می‌دهد که می‌خواهیم مقیاس محتوای ما به اندازه‌ی عرض دستگاه(device) مورد نظر باشد و initial-scale هم مقدار زوم را برای Web page ما مشخص می‌کند. شما می‌توانید با مقدار دهی user-scalable=no هم امکان تغییر زوم را به کاربر ندهید. این متا تگ را در تمام صفحات html خود بعد از تگ title قرار دهید.

روال کار jQuery Mobile
برای اینکه بتواند سند HTML ما را برای استفاده‌ی در موبایل بهینه کند، ابتدا آن را لود می‌کند و سپس بر  اجزایی که با ویژگیdata-role علامت گذاری شده‌اند، CSS3 بهینه شده برای موبایل را اعمال می‌کند.


از آنجایی که مستندات jQuery Mobile به قدر کافی کامل هست، نیازی نیست تا در مورد تک تک آنها مثال بزنیم و از اصل مطلب دور شویم. در هر مثالی که زده خواهد شد، در صورت استفاده از ویجتی خاص، با آن آشنا خواهیم شد.

لیست کامل اتریبیوت‌های -data به همراه مقادیری که می‌پذیرند 

دموی مربوط به ویجت‌ها  

لیست تمام رخدادها 

شما می‌توانید از امکانات Theme Roller برای شخصی سازی تم‌های مورد نیاز استفاده کنید.

لیست کامل کلاس‌های CSS  



Cordova Plugins

از این قسمت http://plugins.cordova.io/#/viewAll و این قسمت  http://plugreg.com/plugins می‌توانید سراغ پلاگین‌های مورد نیاز خود بگردید. برای مثال وارد بخش کانفیگ پروژه شده و از قسمت plugins  و تب Core یکسری از پلاگین‌هایی را که در Cordova گنجانده شده است، مشاهده می‌کنید. با کلیک بر روی دکمه‌ی Add می‌توانید آن را دانلود کرده و از API‌های آن استفاده کنید.



برای مثال پلاگین Notification را به پروژه اضافه می‌کنم. سپس یک فایل js را با نام custom.js به فولدر scripts در ریشه پروژه اضافه کرده و  محتوای فایل‌های index.html , custome.js را به شکل زیر در نظر می‌گیرم:


$(function() {
    $("#alert").on('tap', function(event) {
        navigator.notification.alert("اطلاعات ذخیره شد",null, "alert", "تایید");
    });

    $("#prompt").on('tap', function(event) {
        navigator.notification.prompt("برای تائید نام خود را وارد کنید", onPrompt, "prompt", "تایید", "لغو"],"نام خود"]);
    });

    function onPrompt(results) {
        navigator.notification.alert(results.buttonIndex + "\n" + results.input1, null);
    }
    $("#confirm").on('tap', function(event) {
        navigator.notification.confirm("حذف انجام شود؟", onConfirm, "confirm", ["بله", "خیر", "نمیدانم"]);
    });

    function onConfirm(buttonIndex) {
        navigator.notification.alert(buttonIndex , null);
    }
    $("#beep").on('tap', function(event) {
        navigator.notification.beep(1);
    });

});

رخداد tap زمانی صادر می‌شود که کاربر، دکمه‌ی مورد نظر را لمس کند و یکی از رخداد‌های jQuery Mobile می‌باشد. بعد از نصب پلاگین Notification، با استفاده از navigator.notification می‌توانید به متد‌های مورد نظر که در بالا مشخص است، دسترسی پیدا کنید.

برای آشنایی با این پلاگین می‌توانید داکیومنت آن را مطالعه کنید.

در کد بالا با استفاده از متد‌های callback توانسته‌ایم اطلاعاتی در مورد نوع عملکرد کاربر با notification ما بدست آوریم.


<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title>CordovaApp01</title>
   <meta name="viewport" content="width=device-width, initial-scale=1"/> 
    <!-- CordovaApp01 references -->
    <link href="css/index.css" rel="stylesheet" />
    <link href="jquery.mobile.rtl/css/themes/default/rtl.jquery.mobile-1.4.0.css" rel="stylesheet" />
</head>
<body>
<div data-role="page" id="page1">
    <div data-role="header">
        <h2>
            تست پلاگین Notification
        </h2>
    </div>
    <div data-role="content">
        <a href="#page2" data-transition="pop" data-rel="dialog" data-role="button" data-inline="true" data-icon="back">page 2</a>
       
        <button data-role="button" id="alert" data-inline="true" >alert</button>
        <button data-role="button" id="confirm" data-inline="true">confirm</button>
        <button data-role="button" id="beep" data-inline="true" >beep</button>
        <button data-role="button" id="prompt" data-inline="true" >prompt</button>

    </div>
    <div data-role="footer">
        <h2>من فوتر هستم</h2>
    </div>
</div>
    <div data-role="page" id="page2">
        <div data-role="header">
            <h1>Header</h1>
        </div>
        <div data-role="content">
            Content
        </div>
        <div data-role="footer">
            <h1>Footer</h1>
        </div>
    </div>
<!-- Cordova reference, this is added to your app when it's built. -->
    <script src="scripts/jquery-2.1.3.min.js"></script>
    <script src="cordova.js"></script>
    <script src="scripts/platformOverrides.js"></script>
    <script src="scripts/index.js"></script>
    <script src="jquery.mobile.rtl/js/rtl.jquery.mobile-1.4.0.js"></script>
    <script src="scripts/custom.js"></script>
</body>
</html>

در کد بالا 4 تا button دیده می‌شود که ویژگی data-role آنها مقدار button در نظر گرفته شده‌است تا توسط jQuery Mobile به عنوان button شناخته شوند و استایل‌های لازم بر روی آن‌ها اعمال گردد. قرار است طبق کد js ایی که نوشته‌ایم، با لمس کردن هر کدام از دکمه‌ها، notification هایی نمایش داده شوند.


برای اینکار شبیه ساز YouWave را دانلود کرده و نصب کنید. سپس در قسمت toolbar ویژوال، گزینه‌ی Device را به جای شبیه ساز Ripple انتخاب کنید. نرم افزار youwave را اجرا کنید حال اگر برنامه را اجرا کنید با خطای زیر مواجه خواهید شد:

Error447C:\Users\Administrator\Documents\Visual Studio 2013\Projects\CordovaApp-01\CordovaApp-01\bld\Debug\platforms\android\cordova\node_modules\q\q.js:126CordovaApp-01
Error448throw e;CordovaApp-01
Error449^CordovaApp-01
Error450Error : DEP10201 : Failed to deploy to device, no devices found.CordovaApp-01
مشخصا خطا، مبنی بر پیدا نشدن دستگاه خارجی است. برای رفع این مشکل می‌بایست شبیه ساز youwave را به ویژوال استودیو وصل کنیم. برای این منظور دستور زیر را در cmd اجرا کنید.
adb connect localhost:5558

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


علاوه بر این ما در سند HTML خود در بالا، یک page و یک تگ a قرار داده‌ایم. 
 <a href="#page2" data-transition="pop" data-rel="dialog" data-role="button" data-inline="true" data-icon="back">page 2</a>
data-role: با مقدار button در نظر گرفته شده است؛ لذا به شکل 4 دکمه دیگر رندر خواهد شد.
data-transition: با مقدار pop در نظر گرفته شده است که مشخص کننده‌ی افکت ظاهر شدن صفحه‌ای است که قرار است بار گذاری شود.
data-rel: مشخص می‌کند که صفحه‌ی مورد نظر من به صورت دیالوگ باز شود.
data-icon: با استفاده از این ویژگی می‌توان icon مورد نظر خود را برای المنت در نظر گرفت.
data-inline: برای به خط کردن دکمه‌ها کنار هم استفاده می‌شود.
با لمس کردن این دکمه، نتیجه به شکل زیر خواهد بود:

در مقاله‌ی بعد، به مباحث Database در Cordova خواهیم پرداخت.

ادامه دارد...

نظرات مطالب
سفارشی کردن قابلیت طراحی ریپورت توسط END USER - بخش اول
با سلام
Viewer رو چطور میشه از Codebehind تنظیم کرد که به صورت پیش فض با Office 2010 Blue لود بشه و فرم Please Select type of Infterface نمایش داده نشه . چون این کدی که نوشتید کار نمی‌کنه
  //تنظیم تم ریپورت از حالت استاندارد به ریبون
            StiOptions.Windows.GlobalGuiStyle = StiGlobalGuiStyle.Office2010Blue;
            //فعال سازی تم ریبون
            StiOptions.Designer.IsRibbonGuiEnabled = true;
با تشکر
نظرات اشتراک‌ها
Workrave؛ برنامه‌ای جهت یادآوری نیاز به کمی استراحت!
لطفا یه روتین برای مراقبت از چشم پیشنهاد بدین . مثلا تم ویژال استودیو چی باشه. قطره چشم استفاده کنیم یا...
برای مراقبت از گردن هم راهنمایی کنید که چطور مراقبت کنیم ت مشکلات ارتروز گردن و... نگیریم.
مرسی