مطالب
نمایش در حال بارگذاری بودن صفحه در برنامه‌های Angular
پیشتر در مورد HTTP Client جدید Angular، مطلب «ارتقاء به HTTP Client در Angular 4.3» را بررسی کردیم. یکی دیگر از قابلیت‌های HttpClient که روش اصلی دسترسی به اطلاعات از راه دور در Angular 5 نیز می‌باشد، امکان تعریف Interceptors سفارشی برای آن است. به کمک Interceptors می‌توان به تمامی درخواست‌های HTTP ارسالی و پاسخ‌های دریافتی از سرور گوش فرا داد و در این بین منطق ویژه‌ای را پیاده سازی کرد؛ مانندcaching ،logging و غیره. در مطلب جاری قصد داریم از این قابلیت برای نمایش یک loading bar مشخص کننده‌ی شروع و پایان تمامی درخواست‌های HTTP استفاده کنیم.


دریافت و نصب پیشنیازها

برای نمایش loading bar در بالای صفحه، از کامپوننت ng2-slim-loading-bar استفاده خواهیم کرد. دمویی از آن‌را در اینجا می‌توانید مشاهده کنید.
برای نصب آن، ابتدا دستور ذیل را در ریشه‌ی پروژه اجرا کنید:
 npm install ng2-slim-loading-bar --save
پس از آن فایل angular-cli.json. را گشوده و فایل css آن‌را تعریف نمائید:
"styles": [
   "../node_modules/ng2-slim-loading-bar/style.css",
   "styles.css"
],
در ادامه به فایل app.module.ts مراجعه کرد و ماژول آن‌را نیز به نحو ذیل به برنامه معرفی کنید:
import {SlimLoadingBarModule} from 'ng2-slim-loading-bar';

@NgModule({
imports: [
     //...
     SlimLoadingBarModule.forRoot()
  ]
})
export class AppModule {
}

پس از این مقدمات، هرجایی که نیاز به استفاده‌ی از آن با کدنویسی باشد، ابتدا سرویس SlimLoadingBarService آن‌را به سازنده‌ی کلاس کامپوننت مدنظر تزریق می‌کنیم و سپس از متدهای start ،stop و complete آن می‌توان استفاده کرد.
 import {SlimLoadingBarService} from 'ng2-slim-loading-bar';
همچنین برای نمایش این کامپوننت باید selector آن را در فایل app.component.html در بالای صفحه اضافه کرد:
  <ng2-slim-loading-bar></ng2-slim-loading-bar>


تدارک یک LoaderInterceptor برای استفاده از ng2-slim-loading-bar

در ادامه می‌خواهیم هر زمانیکه در سراسر برنامه، درخواست HTTP ایی شروع شد، این کامپوننت نمایش داده شود و در پایان درخواست و یا درصورت بروز خطایی، پایان یابد و مخفی شود. برای این منظور یک Interceptor جدید را به صورت ذیل به پوشه‌ی Core برنامه اضافه می‌کنیم:
 ng g s core/interceptors/LoaderInterceptor --spec false
با این کدها:
import { Injectable } from "@angular/core";
import { HttpEvent, HttpHandler, HttpInterceptor, HttpRequest, HttpResponse } from "@angular/common/http";
import { Observable } from "rxjs/Observable";
import "rxjs/add/operator/do";
import { SlimLoadingBarService } from "ng2-slim-loading-bar";


@Injectable()
export class LoaderInterceptorService implements HttpInterceptor {

  constructor(private loadingBar: SlimLoadingBarService) {
  }

  intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    // start our loader here
    this.loadingBar.start();
    return next.handle(req).do(
      (event: HttpEvent<any>) => {
        if (event instanceof HttpResponse) {
          this.loadingBar.complete();
        }
      },
      (err: any) => {
        this.loadingBar.complete();
      });
  }
}
توضیحات:
- برای پیاده سازی یک interceptor جدید، نیاز است کلاس سرویسی را که HttpInterceptor را پیاده سازی می‌کند، ایجاد کنیم. برای تکمیل این پیاده سازی نیاز است متد intercept را با امضایی که مشاهده می‌کنید، تعریف کنیم:
 intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
- در اینجا پارامتر req به خود درخواست Http اشاره می‌کند.
- کار پارامتر next تنظیم و بازگشت یک HttpEvent observable توسط متد handle آن است.

برای نمونه در اینجا ابتدا سرویس SlimLoadingBarService به سازنده‌ی کلاس interceptor‌  تزریق شده‌است. سپس توسط آن می‌توان به متدهای start و complete این کامپوننت دسترسی یافت. برای مثال در ابتدای کار گوش فرادادن به درخواست جاری، متد start فراخوانی شده‌است و سپس زمانیکه پاسخی از سرور دریافت شده و یا خطایی رخ‌داده، متد complete آن فراخوانی شده‌است.


ثبت و معرفی LoaderInterceptorService به سیستم

برای معرفی interceptor تهیه شده، به فایل app.module.ts مراجعه کرد و قسمت providers آن‌را به نحو ذیل تکمیل می‌کنیم: 
 @NgModule({
  providers: [
   { provide: HTTP_INTERCEPTORS, useClass: LoaderInterceptorService, multi: true }
  ]
})
export class AppModule {}


آزمایش برنامه

اکنون اگر قسمت‌های مختلف برنامه را که با HttpClient جدید کار می‌کنند بررسی کنید، متوجه خواهید شد که با شروع هر درخواست، loading bar قرمزی در بالای صفحه ظاهر می‌شود و در پایان درخواست، به صورت خودکار مخفی می‌گردد. نکته‌ی مهم این روش عدم نیاز به تغییری در قسمت‌های مختلف برنامه است. این interceptor سراسری است و به صورت یکسانی بر روی کل برنامه تاثیر می‌گذارد.
نظرات اشتراک‌ها
سرویس دهی رایگان Google Maps از فردا خاتمه می‌یابد
سرویس نقشه گوگل به سه دسته کلی maps, routes, places  تقسیم شده که تحت عنوان Google Map Platform کار خواهند کرد و شامل قوانین جدید گوگل برای نقشه میشه
نظرات مطالب
Angular CLI - قسمت پنجم - ساخت و توزیع برنامه
- System JS منسوخ شده را در اولین قسمت‌های Angular ارائه شده‌ی در این سایت می‌توانید پیدا کنید. این روش با CLI آن جایگزین شده.
- فایل index.html ای را که در نهایت تولید کرده باز کنید. تمام تگ‌های اسکریپت ذکر شده‌ی در آن‌را نیاز خواهید داشت (بیشتر از یک مورد است).
نظرات مطالب
شروع به کار با AngularJS 2.0 و TypeScript - قسمت اول - نصب پیشنیازها
اگر امکانش هست ساختار یه پروژه ASP .NET MVC با استفاده از angular CLI رو بذارید. منظورم اینه که اگر بخواهیم از این دو استفاده کنیم ساختار پروژه در حالت استاندارد به چه صورتی باید باشد.
مطالب
فرم‌های مبتنی بر قالب‌ها در Angular - قسمت اول - معرفی و ایجاد ساختار برنامه
پیشنیازها
- آشنایی با Angular CLI
- آشنایی با مسیریابی‌ها در Angular

همچنین اگر پیشتر Angular CLI را نصب کرده‌اید، قسمت «به روز رسانی Angular CLI» ذکر شده‌ی در مطلب «Angular CLI - قسمت اول - نصب و راه اندازی» را نیز اعمال کنید. در این سری از angular/cli: 1.1.2@ استفاده شده‌است.


فناوری‌های مختلف کار با فرم‌ها در Angular

Angular (که خلاصه شده‌ی نام تمام نگارش‌های پس از Angular 2 است)، به همراه دو فناوری توکار کار با فرم‌ها است:
الف) فرم‌های مبتنی بر قالب‌ها یا Template driven forms
در اینجا عمده‌ی کار تعاریف فرم‌ها، در قالب‌های HTML ایی کامپوننت‌ها به همراه data binding انجام می‌شود. کار با آن ساده‌تر است و به همراه حداقل کدنویسی در قسمت کامپوننت‌های برنامه است؛ چون two-way data binding بسیاری از مسایل را به صورت خودکار مدیریت می‌کند. همچنین این روش برای کسانیکه با Angular 1.x کار کرده باشند، آشناتر است.
ب) فرم‌های واکنشی یا Reactive forms
در اینجا نیز همانند حالت الف کار تعریف ابتدایی فرم در قالب‌های HTML ایی کامپوننت‌ها انجام می‌شود. اما در اینجا نیاز است مدل فرم را توسط کدهای TypeScript کامپوننت نیز ایجاد کرد و با قالب HTML ایی هماهنگ نمود (به همین جهت به آن model driven forms هم می‌گویند). مزیت این روش نسبت به حالت الف، سادگی Unit testing و همچنین امکان تعریف اعتبارسنجی‌های پیچیده‌است. به علاوه در این حالت می‌توان فرم‌های پویایی را نیز طراحی کرد.

ما در این سری حالت Template driven forms را بررسی خواهیم کرد.


ایجاد ساختار اولیه‌ی مثال این سری

در ادامه، یک پروژه‌ی جدید مبتنی بر Angular CLI را به نام angular-template-driven-forms-lab به همراه تنظیمات ابتدایی مسیریابی آن ایجاد می‌کنیم:
 > ng new angular-template-driven-forms-lab --routing
به علاوه، قصد استفاده‌ی از بوت استرپ را نیز داریم. به همین جهت ابتدا به ریشه‌ی پروژه وارد شده و سپس دستور ذیل را صادر کنید، تا بوت استرپ نصب شود و پرچم save آن سبب به روز رسانی فایل package.json نیز گردد:
 > npm install bootstrap --save
پس از آن نیاز است به فایل angular-cli.json. مراجعه کرده و شیوه‌نامه‌ی بوت استرپ را تعریف کنیم:
  "apps": [
    {
      "styles": [
    "../node_modules/bootstrap/dist/css/bootstrap.min.css",
        "styles.css"
      ],
به این ترتیب، به صورت خودکار این شیوه نامه به همراه توزیع برنامه حضور خواهد داشت و نیازی به تعریف مستقیم آن در فایل index.html نیست.

در ادامه برای تکمیل مثال جاری، دو کامپوننت جدید خوش‌آمدگویی و همچنین یافتن نشدن مسیرها را به برنامه اضافه می‌کنیم:
>ng g c welcome
>ng g c PageNotFound
که سبب ایجاد کامپوننت‌های src\app\welcome\welcome.component.ts و src\app\page-not-found\page-not-found.component.ts خواهند شد؛ به همراه به روز رسانی خودکار فایل src\app\app.module.ts جهت تکمیل قسمت declarations آن:
@NgModule({
  declarations: [
    AppComponent,
    WelcomeComponent,
    PageNotFoundComponent
  ],

سپس فایل src\app\app-routing.module.ts را به نحو ذیل تکمیل نمائید:
import { PageNotFoundComponent } from './page-not-found/page-not-found.component';
import { WelcomeComponent } from './welcome/welcome.component';
import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';

const routes: Routes = [
  { path: 'welcome', component: WelcomeComponent },
  { path: '', redirectTo: 'welcome', pathMatch: 'full' },
  { path: '**', component: PageNotFoundComponent }
];

@NgModule({
  imports: [RouterModule.forRoot(routes)],
  exports: [RouterModule]
})
export class AppRoutingModule { }
در اینجا زمانیکه کاربر ریشه‌ی سایت را درخواست می‌کند، به کامپوننت welcome هدایت خواهد شد.
همچنین مدیریت مسیریابی آدرس‌های ناموجود در سایت نیز با تعریف ** صورت گرفته‌است.

زمانیکه یک کامپوننت فعالسازی می‌شود، قالب آن در router-outlet نمایش داده خواهد شد. برای این منظور فایل src\app\app.component.html را گشوده و به نحو ذیل تغییر دهید:
<nav class="navbar navbar-default">
  <div class="container-fluid">
    <a class="navbar-brand">{{title}}</a>
    <ul class="nav navbar-nav">
      <li>
        <a [routerLink]="['/']">Home</a>
      </li>
    </ul>
  </div>
</nav>
<div class="container">
  <router-outlet></router-outlet>
</div>
تا اینجا اگر دستور ng serve -o را صادر کنیم (کار build درون حافظه‌ای جهت محیط توسعه و نمایش خودکار برنامه در مرورگر)، چنین خروجی در مرورگر نمایان خواهد شد:



افزودن ماژول فرم‌ها به برنامه

پس از ایجاد ساختار اولیه برنامه، اولین کاری را که در جهت استفاده‌ی از فرم‌های مبتنی بر قالب‌ها باید انجام داد، افزودن ماژول فرم‌ها به ماژول اصلی برنامه است. برای این منظور فایل src\app\app.module.ts را گشوده و تغییرات ذیل را به آن اعمال کنید:
import { FormsModule } from '@angular/forms';

@NgModule({
  imports: [
    BrowserModule,
    FormsModule,
    AppRoutingModule
  ]
در اینجا ابتدا FormsModule، از ماژول Angular مرتبط با آن دریافت شده و سپس به لیست imports ماژول اصلی برنامه اضافه گردیده‌است.


ایجاد ماژول و کامپوننت فرم ثبت نام کارمندان

در ادامه می‌خواهیم فرم ثبت نام یک کارمند را تکمیل کنیم. بنابراین ماژول جدید کارمندان را به همراه تنظیمات ابتدایی مسیریابی آن ایجاد می‌کنیم:
 >ng g m Employee -m app.module --routing
با این خروجی
 installing module
  create src\app\employee\employee-routing.module.ts
  create src\app\employee\employee.module.ts
  update src\app\app.module.ts
اگر به سطر آخر آن دقت کنید، فایل app.module.ts را نیز به صورت خودکار به روز رسانی کرده‌است:
import { EmployeeRoutingModule } from './employee/employee-routing.module';

@NgModule({
  imports: [
    BrowserModule,
    FormsModule,
    AppRoutingModule,
    EmployeeRoutingModule
  ]
در اینجا EmployeeRoutingModule را به انتهای لیست imports افزوده‌است که نیاز به اندکی تغییر دارد و باید EmployeeRoutingModule را پیش از AppRoutingModule تعریف کرد. علت این است که AppRoutingModule، دارای تعریف مسیریابی ** یا catch all است که آن‌را جهت مدیریت مسیرهای یافت نشده به برنامه افزوده‌ایم. بنابراین اگر ابتدا AppRoutingModule تعریف شود و سپس EmployeeRoutingModule، هیچگاه فرصت به پردازش مسیریابی‌های ماژول کارمندان نمی‌رسد؛ چون مسیر ** پیشتر برنده شده‌است.
همچنین برای اینکه کامپوننت‌های این ماژول نیز در حین مسیریابی در دسترس باشند، نیاز است بجای EmployeeRoutingModule، خود EmployeeModule را ذکر کرد که حاوی تعاریف مسیریابی (ذکر EmployeeRoutingModule در قسمت imports آن) نیز می‌باشد. بنابراین فایل app.module.ts چنین تعاریفی را پیدا می‌کند:
import { EmployeeModule } from './employee/employee.module';

@NgModule({
  imports: [
    BrowserModule,
    FormsModule,    
    EmployeeModule,
    AppRoutingModule 
  ]

در ادامه کامپوننت جدید ثبت یک کارمند را به این ماژول اضافه می‌کنیم:
 >ng g c employee/employee-register
با این خروجی
 installing component
  create src\app\employee\employee-register\employee-register.component.css
  create src\app\employee\employee-register\employee-register.component.html
  create src\app\employee\employee-register\employee-register.component.spec.ts
  create src\app\employee\employee-register\employee-register.component.ts
  update src\app\employee\employee.module.ts
اگر به سطر آخر آن دقت کنید، کار به روز رسانی فایل ماژول کارمندان، جهت درج این کامپوننت جدید، در قسمت declarations فایل employee.module.ts نیز به صورت خودکار انجام شده‌است:
import { EmployeeRegisterComponent } from './employee-register/employee-register.component';

@NgModule({
  declarations: [EmployeeRegisterComponent]

در ادامه می‌خواهیم قالب این کامپوننت را در منوی اصلی سایت قابل دسترسی کنیم. به همین جهت به فایل src\app\employee\employee-routing.module.ts مراجعه کرده و مسیریابی این کامپوننت را تعریف می‌کنیم:
import { EmployeeRegisterComponent } from './employee-register/employee-register.component';

const routes: Routes = [
  { path: 'register', component: EmployeeRegisterComponent }
];
ابتدا کامپوننت ثبت کارمندان import شده و سپس آرایه‌ی Routes مسیری را به این کامپوننت تعریف کرده‌است.

سپس می‌خواهیم لینکی را به این مسیریابی جدید اضافه کنیم. به همین جهت به فایل src\app\app.component.html مراجعه کرده و routerLink آن‌را اضافه می‌کنیم:
    <ul class="nav navbar-nav">
      <li>
        <a [routerLink]="['/']">Home</a>
      </li>
      <li>
        <a [routerLink]="['/register']">Register</a>
      </li>
    </ul>
تا اینجا اگر دستور ng serve -o را صادر کنیم (کار build درون حافظه‌ای جهت محیط توسعه و نمایش خودکار برنامه در مرورگر)، چنین خروجی در مرورگر نمایان خواهد شد (البته می‌توان پنجره‌ی کنسول ng serve را باز نگه داشت تا کار watch را به صورت خودکار انجام دهد؛ این روش سریعتر و به همراه build تدریجی است):



در قسمت بعد، ایجاد اولین فرم مبتنی بر قالب‌ها را پیگیری می‌کنیم.


کدهای کامل این قسمت را از اینجا می‌توانید دریافت کنید: angular-template-driven-forms-lab-01.zip
برای اجرای آن فرض بر این است که پیشتر Angular CLI را نصب کرده‌اید. سپس از طریق خط فرمان به ریشه‌ی پروژه وارد شده و دستور npm install را صادر کنید تا وابستگی‌های آن دریافت و نصب شوند. در آخر با اجرای دستور ng serve -o برنامه ساخته شده و در مرورگر پیش فرض سیستم نمایش داده خواهد شد.
مطالب
Angular CLI - قسمت سوم - تولید کد
پس از ایجاد ساختار اولیه‌ی یک برنامه‌ی Angular توسط Angular CLI، امکان تولید کدهای کامپوننت‌ها، ماژول‌ها، سرویس‌ها و ... نیز در این ابزار پیش بینی شده‌است. کدهای تولید شده‌ی آن بر اساس یک سری blueprint (و یا همان مفهوم قالب‌های از پیش آماده در سایر ابزارهای مشابه) ایجاد می‌شوند و فرمت کلی آن نیز به صورت ذیل است:
> ng generate <blueprint> <options>


ایجاد کامپوننت‌های جدید توسط Angular CLI

دستور ایجاد یک کامپوننت جدید توسط Angular CLI به نحو زیر است:
> ng generate component customer
این دستور اندکی طولانی به نظر می‌رسد. به همین جهت برای خلاصه نویسی آن می‌توان از مفهومی به نام Alias استفاده کرد. میانبر generate در اینجا g است و میانبر component، معادل c می‌باشد. به این صورت می‌توان دستور فوق را به این شکل، خلاصه و بازنویسی کرد:
> ng g c customer


گزینه‌های ایجاد کدهای جدید در Angular CLI

اگر به اولین دستور بحث جاری دقت کنید، قسمت <options> نیز برای آن درنظر گرفته شده‌است. تعدادی از مهم‌ترین گزینه‌هایی را که در اینجا می‌توان ذکر کرد به شرح زیر هستند:

گزینه 
Alias (میانبر/نام مستعار)      توضیح 
 flat--
    آیا باید برای آن پوشه‌ای ایجاد نشود؟ (flat = بدون پوشه در اینجا)
 (پیش فرض آن ایجاد یک پوشه‌ی جدید است). اگر می‌خواهیم ایجاد نشود، باید flat true-- را ذکر کرد. 
inline-template--  it-  آیا قالب کامپوننت، درون فایل ts. آن قرار گیرد؟ (پیش فرض آن، false است) 
 inline-style--  is-  آیا شیوه نامه‌ی کامپوننت، داخل فایل ts. آن قرار گیرد؟ (پیش فرض آن، false است) 
 spec--    آیا فایل spec نیز تولید شود؟
(پیش فرض آن true است) اگر می‌خواهیم این فایل ایجاد نشود باید spec false-- را ذکر کرد. 
 view-encapsulation--
 ve-  تعیین نوع استراتژی view encapsulation مورد استفاده (مانند Emulated). 
 change-detection--  cd-  تعیین استراتژی change detection مورد استفاده (مانند OnPush). 
 dry-run--  d-  گزارش فایل‌های تولیدی، بدون نوشتن و تولید آن‌ها (پیش فرض آن false است) 
 prefix--    تعیین صریح prefix مورد استفاده‌ی در حین مقدار دهی selectorها که در قسمت قبل در مورد آن بحث شد. 

برای مثال اگر خواستیم کامپوننتی را به همراه قالب‌ها و شیوه‌نامه‌های inline (قرار گرفته‌ی داخل فایل ts. آن) تولید کنیم، می‌توان از دستور ذیل کمک گرفت:
>ng generate component customer --inline-template --inline-style
که خلاصه شده‌ی آن با توجه به Alias‌های ذکر شده به صورت ذیل است:
>ng g c customer –it -is

اگر صرفا دستور ng generate component customer را اجرا کنیم (بدون هیچ گزینه‌ی اضافه‌تری)، فایل‌های ts (کلاس کامپوننت)، css (فایل شیوه نامه)، html (فایل قالب) و spec (فایل آزمون واحد کامپوننت) به صورت خودکار تولید خواهند شد.

همانطور که پیشتر نیز عنوان شد، اگر مطمئن نیستید که دستور درحال فراخوانی، چه فایل‌ها و پوشه‌هایی را ایجاد می‌کند، با ذکر پرچم dry-run-- و یا به صورت خلاصه d-، دستور مدنظر را شبیه سازی کنید تا صرفا گزارشی را از فایل‌هایی که قرار است تولید شوند، ارائه دهد.

نکته‌ی مهم دیگری که به همراه دستورات Angular CLI هستند، به روز رسانی خودکار فایل app.module.ts است:
>ng g c customer
installing component
  create src\app\customer\customer.component.css
  create src\app\customer\customer.component.html
  create src\app\customer\customer.component.spec.ts
  create src\app\customer\customer.component.ts
  update src\app\app.module.ts
برای نمونه زمانیکه دستور تولید یک کامپوننت را به نحوی که ملاحظه می‌کنید صادر کنیم، علاوه بر ایجاد 4 فایل مرتبط با آن کامپوننت، سطر به روز رسانی فایل app.module.ts را نیز در انتها ذکر کرده‌است. در اینجا تغییرات صورت گرفته را ملاحظه می‌کنید:
 import { CustomerComponent } from './customer/customer.component';

@NgModule({
  declarations: [
   AppComponent,
   CustomerComponent
]})
ابتدا به صورت خودکار سطر import این کامپوننت جدید ذکر شده‌است و سپس قسمت declarations ماژول را نیز با تعریف CustomerComponent به روز رسانی کرده‌است. بنابراین کار با Angular CLI فراتر است از صرفا کار با تعدادی قالب از پیش آماده‌ی کامپوننت‌ها و سرویس‌ها.


مشاهده‌ی تغییرات انجام شده‌ی توسط Angular CLI به کمک سورس کنترل

همانطور که در قسمت قبل نیز عنوان شد، دستور ng new، کار آغاز یک مخزن Git را نیز به صورت خودکار انجام می‌دهد. در اینجا هر دستوری که توسط Angular CLI اجرا شود، به این مخزن کد commit خواهد شد.


برای مثال اگر کل پوشه‌ی برنامه را توسط VSCode باز کنیم (کلیک راست در داخل ریشه‌ی اصلی پروژه و انتخاب گزینه‌ی Open With Code)، با مراجعه‌ی به لیست تغییرات و بررسی diff آن‌ها، به سادگی می‌توان تشخیص داد که چه تغییراتی بر روی فایل‌ها اعمال شده‌اند.


ایجاد سایر اجزای جدید برنامه توسط Angular CLI

نام جزء
 Alias  دستور
 service   s   ng g service customer-data 
 pipe  p   ng g pipe init-caps 
 class   cl   ng g class customer-model 
 directive   d   ng g directive search 
 interface   i   ng g interface orders 
 enum  e   ng g enum gender 
 module  m   ng generate module sales 

نکات تکمیلی
 - در حین ایجاد یک directive جدید، پوشه‌ای را برای آن ایجاد نمی‌کند. اگر می‌خواهید اینکار به صورت flat (بدون پوشه در اینجا) انجام نشود، گزینه‌ی flat false-- را نیز قید کنید.
 - در حین ایجاد یک سرویس جدید، اخطار «WARNING Service is generated but not provided, it must be provided to be used» را دریافت خواهید کرد. علت اینجا است که Angular CLI نمی‌داند که این سرویس را باید به کامپوننت خاصی اضافه کند یا به ماژول برنامه. به همین جهت یا باید به صورت دستی فایل src\app\app.module.ts را ویرایش و قسمت providers آن‌را بر اساس نام این سرویس جدید تکمیل کرد و یا توسط سوئیچ m می‌توان ماژول مدنظر را دقیقا ذکر کرد:
> ng g s sales -m app.module
در اینجا عنوان شده‌است که پس از ایجاد سرویس جدید sales، قسمت providers ماژول src\app\app.module.ts نیز به روز رسانی شود.
این نکته در مورد تمام اجزایی که فایل app.module را به روز رسانی می‌کنند نیز صادق است. اگر برای مثال کامپوننتی قرار است ماژول جدید دیگری را به روز رسانی کند، می‌توانید به صورت صریح نام ماژول آن‌را قید کنید؛ در غیراینصورت از همان app.module پیش فرض استفاده خواهد شد.
 - همانطور که مشاهده می‌کنید امکان تولید کلاس، اینترفیس و enum تایپ‌اسکریپتی نیز در اینجا پیش بینی شده‌است. اگر خواستید کلاسی را درون پوشه‌ی خاصی قرار دهید می‌توانید محل پوشه‌ی آن‌را دقیقا ذکر کنید (در مورد اینترفیس‌ها و enums و سایر اجزاء نیز به همین صورت):
> ng g cl models/customer
به این ترتیب فایل کلاس customer.ts درون پوشه‌ی arc/app/models تشکیل می‌شود. پوشه‌ی models نیز در صورت عدم وجود به صورت خودکار ایجاد خواهد شد.


تغییر تنظیمات پیش فرض تولید کد پروژه‌ی جاری

در قسمت قبل «تغییر پیش فرض‌های عمومی Angular CLI» را بررسی کردیم. در اینجا نیز می‌توان یکسری از خواص فایل angular-cli.json. را بازنویسی کرد؛ در قسمت defaults آن:
"defaults": {
    "styleExt": "css",
    "component": {}
}
یا از طریق خط فرمان
> ng set defaults.component.flat false
> ng set defaults.directive.flat false
> ng set defaults.styleExt sass
و یا با ویرایش فایل json تنظیمات cli به صورت مستقیم:
  "defaults": {
    "styleExt": "sass",
    "component": {
      "flat": false
    },
    "directive": {
      "flat": false
    }
  }
به این ترتیب دیگر نیازی نخواهد بود تا هربار به ازای ایجاد یک دایرکتیو جدید، پرچم flat نبودن آن‌را مقدار دهی کرد؛ چون از فایل angular-cli.json. تنظیمات خودش را دریافت می‌کند.


و اگر VSCode استفاده می‌کنید، به همراه intellisense کاملی در مورد اجزای مختلف این فایل json است (این intellisense را به صورت خودکار بر اساس اسکیمای این فایل و سرویس زبان Angular تهیه می‌کند).