نظرات مطالب
آشنایی با فریمورک الکترون Electron
با تشکر
سوال1: منظورتون از «در بر گیرنده» چیه؟ (یعنی electron.net و electron-angular-native هر دو زیر مجموعه‌ی الکترون هستند.)
سوال۲: خب وقتی من می‌تونم درون پروژه‌ی الکترونی ام از angular و ... استفاده کنم دیگه چرا باید برم سراغ electron-angular-native؟
نظرات مطالب
سازماندهی برنامه‌های Angular توسط ماژول‌ها
چند نکته‌ی تکمیلی در مورد بهبود تعاریف Shared Module و Core Module

الف) چگونه از import ثانویه‌ی Core Module در سایر ماژول‌ها جلوگیری کنیم؟
Core Module فقط باید در AppModule برنامه import شود و نه در هیچ‌جای دیگری. برای جلوگیری اتفاقی از این مساله می‌توان سازنده‌ای را به شکل زیر به آن اضافه کرد:
@NgModule({
  imports: [CommonModule, RouterModule],
  exports: [], // components that are used in app.component.ts will be listed here.
  declarations: [], // components that are used in app.component.ts will be listed here.
  providers: [BrowserStorageService, AppConfigService] // global singleton services of the whole app will be listed here.
})
export class CoreModule {
  constructor( @Optional() @SkipSelf() core: CoreModule) {
    if (core) {
      throw new Error("CoreModule should be imported ONLY in AppModule.");
    }
  }
};
روش کار به این صورت است که خود CoreModule را به سازنده‌ی همان کلاس تزریق می‌کنیم! اگر وهله‌ای از آن قابل دسترسی بود، یعنی Angular پیشتر این ماژول را import کرده‌است. در این حالت با صدور خطایی این مشکل را گوشزد می‌کنیم.
از همین روش برای تشخیص singleton بودن یک سرویس نیز می‌توان استفاده کرد. خودش را به خودش تزریق می‌کنیم! اگر تزریقی صورت گرفت، یک خطا را صادر می‌کنیم.


ب) چگونه از وهله سازی مجدد سرویس‌های تعریف شده‌ی در Shared Module در سایر ماژول‌ها جلوگیری کنیم؟
هدف از قسمت providers در Shared Module تنها ارائه‌ی سرویس‌هایی جهت کامپوننت‌های اشتراکی آن است؛ وگرنه سرویس‌های سراسری برنامه در CoreModule تعریف می‌شوند و این ماژول ویژه نیز تنها یکبار و آن‌هم در AppModule برنامه import خواهد شد. اما در مورد Shared Module اینطور نیست و اگر این ماژول در یک lazy loaded module استفاده شود، سرویس‌های آن طول عمر متفاوتی را پیدا خواهند کرد (هر lazy loaded module یک injector و یک طول عمر خاص خودش را تعریف می‌کند).
در این حالت برای اینکه سرویس‌های Shared Module فقط در AppModule وهله سازی شوند و نه در هیچ‌جای دیگری، روش کار به صورت ذیل است:
- ابتدا آرایه‌ی providers را از تعاریف NgModule آن حذف می‌کنیم.
- سپس متد ویژه‌ای را به نام forRoot، به کلاس آن اضافه خواهیم کرد:
@NgModule({
  imports: [CommonModule],
  declarations: [], // common and shared components/directives/pipes between more than one module and components will be listed here.
  exports: [CommonModule], // common and shared components/directives/pipes between more than one module and components will be listed here.
  /* No providers here! Since they’ll be already provided in AppModule. */
})
export class SharedModule {
  static forRoot(): ModuleWithProviders {
    // Forcing the whole app to use the returned providers from the AppModule only.
    return {
      ngModule: SharedModule,
      providers: [ /* All of your services here. It will hold the services needed by `itself`. */]
    };
  }
};
متد forRoot به صورت استاتیک تعریف می‌شود و همچنین خروجی از نوع ModuleWithProviders دارد. توسط ModuleWithProviders سبب خواهیم شد، AppModule، این ماژول را به همراه آرایه‌ی providers آن import کند؛ اما سایر ماژول‌ها خیر.
سایر ماژول‌ها چون دسترسی به آرایه‌ی حذف شده‌ی providers این ماژول را ندارند، دیگر نمی‌توانند سرویس‌های آن‌را وهله سازی کنند. اما AppModule با فراخوانی ()SharedModule.forRoot در لیست import خود، تنها یکبار سبب وهله سازی سرویس‌های آن می‌گردد.
بنابراین در اینجا AppModule باید ()SharedModule.forRoot را import کند. سایر ماژول‌ها فقط SharedModule را import می‌کنند (بدون ذکر متد forRoot). به این ترتیب سرویس‌های آن تنها یکبار توسط AppModule در طول عمر برنامه به اشتراک گذاشته می‌شوند و در این حالت تفاوتی نمی‌کند که SharedModule در یک lazy loaded module استفاده شده‌است یا خیر.

روش تعریف متد forRoot توسط سیستم مسیریابی Angular نیز استفاده می‌شود و یک الگوی پذیرفته شده در بین توسعه دهندگان Angular است. برای مثال ()RouterModule.forRoot در AppModule تعریف می‌شود و ()RouterModule.forChild برای سایر ماژول‌ها.

نمونه‌ای از AppModule ، ShardModule و CoreModule
نظرات مطالب
کنترل DatePicker شمسی مخصوص Silverlight 4
با تشکر از جواب سریعتون
کامپوننت رو آوردم و استفاده میکنم ولی موقع اجرای برنامه وقتی stop می‌کنم و می‌خوام به محیط VS 2010 برگردم 2 تاwarning  میده و فرم رو در حالت design نشون نمیده

  1- [A]WpfPersianDatePicker.Views.PDatePicker cannot be cast to [B]WpfPersianDatePicker.Views.PDatePicker. Type A originates from 'WpfPersianDatePicker, Version=1.1.0.0, Culture=neutral, PublicKeyToken=e5d899545a6585ee' in the context 'LoadNeither' at location 'C:\Documents and Settings\HV\Local Settings\Application Data\Microsoft\VisualStudio\10.0\ProjectAssemblies\zgrq7cfx01\WpfPersianDatePicker.DLL'. Type B originates from 'WpfPersianDatePicker, Version=1.1.0.0, Culture=neutral, PublicKeyToken=e5d899545a6585ee' in the context 'Default' at location 'C:\Program Files\Microsoft Visual Studio 10.0\Common7\IDE\WpfPersianDatePicker.dll'
2-
The variable 'UserControl11' is either undeclared or was never assigned. 
فکر می‌کنم خطای دوم همونیه که شما راهنمایی فرمودین ولی من نتونستم جاشو پیدا کنم
یه سوال دیگه من دارم تاریخ رو از پایگاه می‌خونم می‌تونم تو این کامپوننت موقع لود شدن صفحه بنویسمش مثل dateTimepicker معمولی؟
مطالب
شمسی سازی Date-Picker توکار Angular Material 6x
Angular Material به همراه یک کامپوننت Date-Picker بسیار شکیل و حرفه‌ای است اما ... از تقویم شمسی پشتیبانی نمی‌کند. در این مطلب می‌خواهیم با تدارک یک DateAdapter سفارشی، این مشکل را برطرف کنیم تا در نهایت به یک چنین Date-Picker شمسی برسیم:



تاریخچه‌ی تغییرات کامپوننت Date-Picker

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

DateAdapter شمسی تهیه شده از کتابخانه‌ی jalali-moment برای تبدیل تاریخ‌ها استفاده می‌کند. بنابراین ابتدا نیاز است این وابستگی را نصب کرد:
 npm install jalali-moment --save


افزودن DateAdapter شمسی به پروژه

برای افزودن DateAdapter شمسی تهیه شده، فایل جدید app\shared\material.persian-date.adapter.ts را به برنامه اضافه کرده و به صورت زیر تکمیل کنید:
import { DateAdapter } from "@angular/material";
import * as jalaliMoment from "jalali-moment";

export const PERSIAN_DATE_FORMATS = {
  parse: {
    dateInput: "jYYYY/jMM/jDD"
  },
  display: {
    dateInput: "jYYYY/jMM/jDD",
    monthYearLabel: "jYYYY jMMMM",
    dateA11yLabel: "jYYYY/jMM/jDD",
    monthYearA11yLabel: "jYYYY jMMMM"
  }
};

export class MaterialPersianDateAdapter extends DateAdapter<jalaliMoment.Moment> {

  constructor() {
    super();
    super.setLocale("fa");
  }

  getYear(date: jalaliMoment.Moment): number {
    return this.clone(date).jYear();
  }

  getMonth(date: jalaliMoment.Moment): number {
    return this.clone(date).jMonth();
  }

  getDate(date: jalaliMoment.Moment): number {
    return this.clone(date).jDate();
  }

  getDayOfWeek(date: jalaliMoment.Moment): number {
    return this.clone(date).day();
  }

  getMonthNames(style: "long" | "short" | "narrow"): string[] {
    switch (style) {
      case "long":
      case "short":
        return jalaliMoment.localeData("fa").jMonths().slice(0);
      case "narrow":
        return jalaliMoment.localeData("fa").jMonthsShort().slice(0);
    }
  }

  getDateNames(): string[] {
    const valuesArray = Array(31);
    for (let i = 0; i < 31; i++) {
      valuesArray[i] = String(i + 1);
    }
    return valuesArray;
  }

  getDayOfWeekNames(style: "long" | "short" | "narrow"): string[] {
    switch (style) {
      case "long":
        return jalaliMoment.localeData("fa").weekdays().slice(0);
      case "short":
        return jalaliMoment.localeData("fa").weekdaysShort().slice(0);
      case "narrow":
        return ["ی", "د", "س", "چ", "پ", "ج", "ش"];
    }
  }

  getYearName(date: jalaliMoment.Moment): string {
    return this.clone(date).jYear().toString();
  }

  getFirstDayOfWeek(): number {
    return jalaliMoment.localeData("fa").firstDayOfWeek();
  }

  getNumDaysInMonth(date: jalaliMoment.Moment): number {
    return this.clone(date).jDaysInMonth();
  }

  clone(date: jalaliMoment.Moment): jalaliMoment.Moment {
    return date.clone().locale("fa");
  }

  createDate(year: number, month: number, date: number): jalaliMoment.Moment {
    if (month < 0 || month > 11) {
      throw Error(
        `Invalid month index "${month}". Month index has to be between 0 and 11.`
      );
    }
    if (date < 1) {
      throw Error(`Invalid date "${date}". Date has to be greater than 0.`);
    }
    const result = jalaliMoment()
      .jYear(year).jMonth(month).jDate(date)
      .hours(0).minutes(0).seconds(0).milliseconds(0)
      .locale("fa");

    if (this.getMonth(result) !== month) {
      throw Error(`Invalid date ${date} for month with index ${month}.`);
    }
    if (!result.isValid()) {
      throw Error(`Invalid date "${date}" for month with index "${month}".`);
    }
    return result;
  }

  today(): jalaliMoment.Moment {
    return jalaliMoment().locale("fa");
  }

  parse(value: any, parseFormat: string | string[]): jalaliMoment.Moment | null {
    if (value && typeof value === "string") {
      return jalaliMoment(value, parseFormat, "fa");
    }
    return value ? jalaliMoment(value).locale("fa") : null;
  }

  format(date: jalaliMoment.Moment, displayFormat: string): string {
    date = this.clone(date);
    if (!this.isValid(date)) {
      throw Error("JalaliMomentDateAdapter: Cannot format invalid date.");
    }
    return date.format(displayFormat);
  }

  addCalendarYears(date: jalaliMoment.Moment, years: number): jalaliMoment.Moment {
    return this.clone(date).add(years, "jYear");
  }

  addCalendarMonths(date: jalaliMoment.Moment, months: number): jalaliMoment.Moment {
    return this.clone(date).add(months, "jmonth");
  }

  addCalendarDays(date: jalaliMoment.Moment, days: number): jalaliMoment.Moment {
    return this.clone(date).add(days, "jDay");
  }

  toIso8601(date: jalaliMoment.Moment): string {
    return this.clone(date).format();
  }

  isDateInstance(obj: any): boolean {
    return jalaliMoment.isMoment(obj);
  }

  isValid(date: jalaliMoment.Moment): boolean {
    return this.clone(date).isValid();
  }

  invalid(): jalaliMoment.Moment {
    return jalaliMoment.invalid();
  }

  deserialize(value: any): jalaliMoment.Moment | null {
    let date;
    if (value instanceof Date) {
      date = jalaliMoment(value);
    }
    if (typeof value === "string") {
      if (!value) {
        return null;
      }
      date = jalaliMoment(value).locale("fa");
    }
    if (date && this.isValid(date)) {
      return date;
    }
    return super.deserialize(value);
  }
}
کار این Adapter و یا «وفق دهنده» این است که مشخص می‌کند، هفته‌ی ایرانی از چه روزی شروع می‌شود. نام روزهای هفته‌ی ایرانی چیست؟ برچسب‌های نام ماه‌های ایرانی چگونه باید تامین شوند و در کل جهت وفق دادن تقویم میلادی اصلی با تقویم شمسی، چه اجزایی باید به سیستم معرفی شوند تا این تقویم توکار بدون مشکل مانند قبل کار کند.
 
معرفی وفق دهنده‌ی شمسی به پروژه

پس از تعریف MaterialPersianDateAdapter و همچنین PERSIAN_DATE_FORMATS، برای معرفی آن‌ها به برنامه، فایل app\shared\material.module.ts را گشوده و به صورت زیر تغییر دهید:
import { NgModule } from "@angular/core";
import {  DateAdapter,  MAT_DATE_FORMATS,  MAT_DATE_LOCALE } from "@angular/material";

import { MaterialPersianDateAdapter, PERSIAN_DATE_FORMATS } from "./material.persian-date.adapter";

@NgModule({
  providers: [
    { provide: DateAdapter, useClass: MaterialPersianDateAdapter, deps: [MAT_DATE_LOCALE] },
    { provide: MAT_DATE_FORMATS, useValue: PERSIAN_DATE_FORMATS }
  ]
})
export class MaterialModule {
}
کار این تعاریف، تعویض DateAdapter اصلی میلادی، با نمونه‌ی شمسی است. همچنین فرمت نمایشی برچسب‌ها را نیز جایگزین می‌کند.

پس از آن اگر mat-datepicker را به نحو متداولی به صفحه اضافه کنیم:
<mat-form-field>
    <input matInput [matDatepicker]="picker6" placeholder="json gregorian input" [(ngModel)]="dateControl">
    <mat-datepicker-toggle matSuffix [for]="picker6"></mat-datepicker-toggle>
    <mat-datepicker #picker6></mat-datepicker>
</mat-form-field>
یک چنین خروجی حاصل خواهد شد:




چند مثال تکمیلی از کاربردهای کامپوننت mat-datepicker

1) استفاده از تاریخ میلادی رسیده‌ی از سمت سرور و نمایش آن
<mat-form-field>
    <input matInput [matDatepicker]="picker6" placeholder="json gregorian input" [(ngModel)]="dateControl">
    <mat-datepicker-toggle matSuffix [for]="picker6"></mat-datepicker-toggle>
    <mat-datepicker #picker6></mat-datepicker>
</mat-form-field>
با این کدها:
@Component()
export class PersianDatepickerComponent {

  jsonDate = "2018-01-08T20:21:29.4674496";
  dateControl = this.jsonDate;
}
در اینجا jsonDate همان رشته‌ی تاریخی است که از سمت سرور دریافت شده و میلادی است. با انتساب آن به ngModel، به صورت خودکار شمسی نمایش داده خواهد شد:




2) تعیین تاریخ آغاز تقویم و نمایش آن در حالت انتخاب سال
<mat-form-field>
    <input matInput [matDatepicker]="picker2" placeholder="startAt 2017-01-01 and startView=year">
    <mat-datepicker-toggle matSuffix [for]="picker2"></mat-datepicker-toggle>
    <mat-datepicker #picker2 startView="year" [startAt]="startDate"></mat-datepicker>
</mat-form-field>
با این کدها:
import * as moment from "jalali-moment";

@Component()
export class PersianDatepickerComponent  {

  startDate = moment("2017-01-01", "YYYY-MM-DD"); // = moment.from("2017-01-01", "en");
  
}
در این مثال خاصیت startAt را به یک تاریخ میلادی متصل کرده‌ایم و همچنین خاصیت startView به year تنظیم شده‌است که یک چنین خروجی را در بار اول نمایش تقویم ایجاد می‌کند:




3) تعیین باز‌ه‌ی تاریخی قابل انتخاب توسط کاربر
<mat-form-field>
    <input matInput [matDatepicker]="picker3" [min]="minDate" [max]="maxDate" placeholder="min: 2017-10-02 and max: 1396-07-29">
    <mat-datepicker-toggle matSuffix [for]="picker3"></mat-datepicker-toggle>
    <mat-datepicker #picker3></mat-datepicker>
</mat-form-field>
با این کدها:
import * as moment from "jalali-moment";

@Component()
export class PersianDatepickerComponent  {

  minDate = moment.from("2017-10-02", "en"); // = moment('2017-10-02', 'YYYY-MM-DD');
  maxDate = moment.from("1396-07-29", "fa"); // = moment('1396-07-29', 'jYYYY-jMM-jDD');
}
همانطور که ملاحظه می‌کنید کتابخانه‌ی jalali-moment می‌تواند تاریخ شمسی و یا میلادی را توسط متد from آن دریافت کند و هر دو حالت در اینجا پس از انتساب به خواص min و max تقویم، به خوبی کار کرده و سبب محدود ساختن بازه‌ی قابل انتخاب توسط کاربر می‌شوند.



در این تصویر روزهای خاکستری، قابل انتخاب نیستند و غیرفعال شده‌اند (چون min به 10 مهر و max به 29 مهر تنظیم شده‌است).


4) غیرفعال کردن روزهای قابل انتخاب بر اساس یک منطق سفارشی
<mat-form-field>
    <input matInput [matDatepicker]="picker4" [matDatepickerFilter]="myFilter" placeholder="Date validation - Datepicker Filter">
    <mat-datepicker-toggle matSuffix [for]="picker4"></mat-datepicker-toggle>
    <mat-datepicker #picker4></mat-datepicker>
</mat-form-field>
با این کدها:
import * as moment from "jalali-moment";

@Component()
export class PersianDatepickerComponent {

  myFilter = (d: moment.Moment): boolean => {
    const day: number = d.day();
    // Prevent Thursday and Friday from being selected.
    return day !== 5 && day !== 4;
  }
}
در اینجا روزهای پنج‌شنبه و جمعه در تقویم نمایش داده شده، بر اساس تعریف matDatepickerFilter سفارشی، دیگر قابل انتخاب نیستند:



5) کار با رخ‌دادهای تقویم
<mat-form-field>
    <input matInput [matDatepicker]="picker5" (dateInput)="onInput($event)" (dateChange)="onChange($event)"
        placeholder="dateInput and dateChange events">
    <mat-datepicker-toggle matSuffix [for]="picker5"></mat-datepicker-toggle>
    <mat-datepicker #picker5></mat-datepicker>
</mat-form-field>
با این کدها:
import { MatDatepickerInputEvent } from "@angular/material";
import * as moment from "jalali-moment";

@Component()
export class PersianDatepickerComponent {

  onInput(event: MatDatepickerInputEvent<moment.Moment>) {
    console.log("OnInput: ", event.value);
  }

  onChange(event: MatDatepickerInputEvent<moment.Moment>) {
    const x = moment(event.value).format("jYYYY/jMM/jDD");
    console.log("OnChange: ", x);
  }
}
در اینجا نحوه‌ی واکنش نشان دادن به رخ‌دادهای dateInput و dateChange کامپوننت mat-datepicker را ملاحظه می‌کنید:


در اینجا، onInput، با ورود دستی اطلاعات به textbox کامپوننت، فعال می‌شود و onChange، در صورت انتخاب یک تاریخ از تقویم.


کدهای کامل این مثال را از اینجا می‌توانید دریافت کنید.
مطالب
طرحبندی صفحات وب با بوت استرپ 4 - قسمت اول
یکی از مفیدترین قسمت‌های بوت استرپ 4، سیستم طرحبندی و گرید آن است که در ابتدا با یک Container آغاز می‌شود. این Container می‌تواند واکنشگرا و با عرض ثابت باشد و یا fluid انتخاب شود که کل عرض صفحه را به خود اختصاص می‌دهد. داخل هر Container می‌توان ستون‌ها و ردیف‌هایی را تعریف کرد. بوت استرپ 4، یک گرید طرحبندی 12 ستونه را ارائه می‌دهد که برای اندازه‌های زیر، تعدادی break-point را تعریف کرده‌است:
extra small, small, medium, large, extra large
در این نگارش، break-point از نوع extra small، نسبت به نگارش سوم بوت استرپ، جدید است.
به این ترتیب این گرید به شدت انعطاف پذیر شده و می‌توان برای اندازه‌های مختلف صفحه، طرحبندی‌های متفاوتی را ارائه داد.


دربرگیرنده‌ها و ردیف‌های گرید بوت استرپ

گرید طرحبندی بوت استرپ 4، 12 ستونه است و از فناوری خاصی به نام Flexbox استفاده می‌کند. برای کار با آن نیاز است با دو عنصر اصلی زیر آشنا بود:
- Containers: هدف آن‌ها تنظیم طرحبندی، مطابق با break-point (های) خاصی می‌باشد.
- ردیف‌ها و ستون‌ها: طرحبندی اصلی را تشکیل می‌دهند و ردیف‌ها، تعریف ستون‌ها را میسر می‌کنند.


بررسی Grid Containers

در بوت استرپ 4، دو نوع Container با کلاس‌های زیر وجود دارند:
- container: یک دربرگیرنده‌ی متداول است و طرحبندی را در میانه‌ی صفحه و بر اساس break-point (های) خاصی نمایش می‌دهد. این دربرگیرنده، در اطرف آن یک padding با اندازه‌ی 15px را نیز به همراه دارد و با break-pointهای زیر خودش را تطبیق می‌دهد:
extra small: کمتر از 576px
small: بیشتر از 576px
medium: بیشتر از 768px
large: بیشتر از 992px
extra-large: بیشتر از 1200px

- container-fluid: این دربرگیرنده، کل عرض نمایشی صفحه را پوشش می‌دهد.


یک مثال: تعریف container، row و columns

<head>
    <style>
        img {
          width: 100px;
          display: block;
        }
      </style>
</head>

<body>
    <header class="clearfix" style="height: 50vh; background: url(images/background.jpg) no-repeat center center; background-size: cover; margin-bottom: 20px;">
        <div class="container">
            <img src="images/wisdompetlogo.svg" alt="Wisdom Pet Logo">
        </div>
    </header>

    <div class="container">
        <section id="services">
            <div class="row">
                <article class="col">
                    <img class="mx-auto" src="images/icon-exoticpets.svg" alt="Icon">
                    <h3>Exotic Pets</h3>
                    <p>We offer specialized care for reptiles, rodents, birds,
                        and other exotic pets.</p>
                </article>

                <article class="col">
                    <img class="mx-auto" src="images/icon-grooming.svg" alt="Icon">
                    <h3>Grooming</h3>
                    <p>Our therapeutic grooming treatments help battle fleas,
                        allergic dermatitis, and other challenging skin
                        conditions.</p>
                </article>

                <article class="col">
                    <img class="mx-auto" src="images/icon-health.svg" alt="Icon">
                    <h3>General Health</h3>
                    <p>Wellness and senior exams, ultrasound, x-ray, and dental
                        cleanings are just a few of our general health
                        services.</p>
                </article>

                <article class="col">
                    <img class="mx-auto" src="images/icon-nutrition.svg" alt="Icon">
                    <h3>Nutrition</h3>
                    <p>Let our nutrition experts review your pet's diet and
                        prescribe a custom nutrition plan for optimum health
                        and disease prevention.</p>
                </article>

                <article class="col">
                    <img class="mx-auto" src="images/icon-pestcontrol.svg" alt="Icon">
                    <h3>Pest Control</h3>
                    <p>We offer the latest advances in safe and effective
                        prevention and treatment of fleas, ticks, worms, heart
                        worm, and other parasites.</p>
                </article>

                <article class="col">
                    <img class="mx-auto" src="images/icon-vaccinations.svg" alt="Icon">
                    <h3>Vaccinations</h3>
                    <p>Our veterinarians are experienced in modern vaccination
                        protocols that prevent many of the deadliest diseases
                        in pets.</p>
                </article>
            </div>
        </section>
    </div>
</body>
با این خروجی:


توضیحات:
- برای آزمایش این مثال، ابتدا کلاس container آن‌را حذف کنید:
<div class="container">
مشاهده خواهید کرد که کل صفحه بجای نمایش در وسط آن، از سمت چپ و بدون هیچ فاصله‌ای شروع می‌شود. این کلاس container است که محتوا را به میانه‌ی صفحه با فواصلی معین از دو طرف، منتقل می‌کند. به همین جهت عنصرheader  ابتدای آن‌را داخل این container قرار نداده‌ایم تا کل عرض صفحه را پر کند. مقدار height: 50vh، به معنای استفاده‌ی از 50 درصد view-port height است.
اما چون می‌خواهیم محل قرارگیری لوگوی داخل این هدر، با حاشیه‌ی سمت چپ container ذیل آن یکی باشد، این logo را داخل container قرار داده‌ایم.
- از این جهت که تصاویر استفاده شده از نوع svg هستند و بسیار بزرگ می‌باشند، با style تعریف شده‌ی در ابتدای head، اندازه‌ی آن‌ها را کاهش داده‌ایم و همچنین نوع نمایشی آن‌ها را نیز به block تنظیم کرده‌ایم. در این حالت برای اینکه تصاویر در میانه‌ی این block قرار گیرند، از کلاس mx-auto استفاده شده‌است.
- در مرحله‌ی بعد، کار تعریف سطرها و ستون‌ها انجام شده‌است:
    <div class="container">
        <section id="services">
            <div class="row">
                <article class="col">
هر row باید داخل container قرار گیرد. سپس داخل آن می‌توان 12 ستون را تعریف کرد که در اینجا از کلاس col برای این منظور استفاده شده‌است. col ساده‌ترین نوع ستون در بوت استرپ 4 است. کار آن این است که محتوا را تا جائیکه می‌تواند در فضای مهیا نمایش دهد.


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


انواع ستون‌های طرحبندی در بوت استرپ 4

همانطور که عنوان شد، گرید بوت استرپ 4، دارای 12 ستون است. البته در اینجا یک ستون می‌تواند عرض چندین ستون را نیز به خود اختصاص دهد.

در این تصویر، فرمول تعریف کلاس‌های ستون‌ها را در بوت استرپ 4 مشاهده می‌کنید. هر قسمتی از این فرمول که داخل پرانتز قرار گرفته‌است، یعنی ذکر آن اختیاری می‌باشد؛ به همین جهت در مثال قبلی، ذکر صرفا col نیز کار کرد. در این حالت اگر دو ستون را تعریف کنید، هر کدام 50 درصد عرض container را به خود اختصاص می‌دهند و اگر سه ستون تعریف شود، هر کدام 33 درصد عرض را اشغال می‌کنند.
در این فرمول BP به معنای break-point است و یکی از مقادیر ذکر شده‌ی مقابل آن‌را می‌تواند داشته باشد. برای مثال اگر col-sm را تعریف کردیم، یعنی این ستون تا زمانیکه اندازه‌ی صفحه تا 576px باشد، کل عرض صفحه را پر می‌کند.
COL در اینجا به معنای تعداد ستونی است که این محتوا قرار است به خود اختصاص دهد. برای مثال col-md-6 یعنی این ستون تا رسیدن به break-point از نوع md، کل عرض صفحه را به خود اختصاص می‌دهد؛ پس از آن (اندازه‌ی صفحه‌ی بیشتر از 768px) این ستون، 6 واحد از 12 واحد ممکن را به خود اختصاص خواهد داد.
ذکر BP نیز اختیاری است. یعنی اگر تنها col-6 را تعریف کردیم، این ستون در تمام break-pointها و در تمام اندازه‌های ممکن صفحه، همواره 6 واحد از 12 واحد موجود را به خود اختصاص می‌دهد.

مثال: بررسی فرمول تعریف ستون‌ها در بوت استرپ 4

<head>
    <style>
        img {
              width: 100%;
              height: 200px;
              max-height: 200px;
            }
    </style>
</head>

<body>
    <div class="container">
        <div id="services">
            <div class="row">
                <section class="col">
                    <img src="images/image.png" alt="sample image">
                    <h4>Exotic Pets</h4>
                    <p>We offer <strong>specialized</strong> care for <em>reptiles,
                            rodents, birds,</em> and other exotic pets.</p>
                </section>
                <section class="col">
                    <img src="images/image.png" alt="sample image">
                    <h4>Grooming</h4>
                    <p>Our therapeutic <span class="font-weight-bold">grooming</span>
                        treatments help battle fleas, allergic dermatitis, and
                        other challenging skin conditions.</p>
                </section>
                <section class="col">
                    <img src="images/image.png" alt="sample image">
                    <h4>General Health</h4>
                    <p>Wellness and senior exams, ultrasound, x-ray, and dental
                        cleanings are just a few of our general health
                        services.</p>
                </section>
                <section class="col">
                    <img class="img-fluid" src="images/image.png" alt="sample image">
                    <h4>Nutrition</h4>
                    <p>Let our nutrition experts review your pet's diet and
                        prescribe a custom nutrition plan for optimum health
                        and
                        disease prevention.</p>
                </section>
                <section class="col">
                    <img src="images/image.png" alt="sample image">
                    <h4>Pest Control</h4>
                    <p>We offer the latest advances in safe and effective
                        prevention and treatment of fleas, ticks, worms, heart
                        worm, and other parasites.</p>
                </section>
                <section class="col">
                    <img src="images/image.png" alt="sample image">
                    <h4>Vaccinations</h4>
                    <p>Our veterinarians are experienced in modern vaccination
                        protocols that prevent many of the deadliest diseases
                        in
                        pets.</p>
                </section>
            </div>
        </div>
    </div>
</body>
- ابتدا یک container تعریف شده‌است تا محتوا را به میانه‌ی صفحه منتقل کند و همچنین شیوه‌نامه‌های پیش‌فرض بوت استرپ را به آن اعمال نماید.
- سپس کل محتوا را داخل یک ردیف تعریف کرده‌ایم.
- در ادامه هر المان section تعریف شده را به صورت یک col در آورده‌ایم. به این ترتیب بوت استرپ سعی می‌کند تا کل عرض را با ستون‌های تعریف شده تا جائیکه ممکن است پر کند:


و اگر عرض صفحه را کوچک‌تر کنیم، باز هم تاجائیکه ممکن است تعدادی را در سطر اول و مابقی را در سطرهای بعدی جا خواهد داد:


در ادامه می‌خواهیم مشخص کنیم، ستون‌های خاصی، همیشه عرض مشخصی را به خود اختصاص دهند:
    <div class="container">
        <div id="services">
            <div class="row">
                <section class="col-6">
با این خروجی:


در این حالت، اولین ستون تعریف شده، تحت هر حالتی و با هر اندازه‌ی صفحه‌ای، همیشه نصف عرض (6 واحد از 12 واحد) را به خود اختصاص خواهد داد.

مرحله‌ی بعد این است که مشخص کنیم یک ستون در چه اندازه‌ای از صفحه شروع کند به اختصاص دادن عرضی خاص به خود. برای این منظور هر 6 عنصر section تعریف شده را به صورت زیر ویرایش می‌کنیم:
<section class="col-sm">
در این حالت اگر اندازه‌ی صفحه کمتر از این break-point باشد، هر ستون، کل عرض صفحه را به خود اختصاص می‌دهد:


و اگر صفحه را بزرگتر کنیم، مجددا همان حالت تعریف col خالی تکرار می‌شود و بوت استرپ سعی می‌کند در هر سطر، تا جائیکه می‌تواند، تعداد آیتم بیشتری را جا دهد. اگر بخواهیم این تعداد جا دادن‌ها را نیز کنترل کنیم، می‌توان به صورت زیر عمل کرد:
<section class="col-sm-6">
در اینجا col-sm-6 را به هر المان section انتساب داده‌ایم. به این ترتیب باز هم اگر عرض صفحه کمتر از sm باشد، هر آیتم، کل عرض صفحه را به خود اختصاص می‌دهد. اما اگر اندازه‌ی صفحه بیشتر از sm شود، هر آیتم همواره 6 واحد، یا نیمی از عرض را به خود اختصاص خواهد داد:



امکان تعریف بیش از یک break-point برای هر ستون در بوت استرپ 4


در این جدول انواع break-pointهای قابل تعریف توسط بوت استرپ 4 را ملاحظه می‌کنید. تا اینجا تاثیر اعمال تنها یکی از این‌ها را بر روی یک ستون بررسی کردیم؛ اما می‌توان چندین break-point را بر روی یک ستون نیز اعمال کرد. برای مثال اگر به تمام sectionهای مثال این قسمت ترکیب زیر را اضافه کنیم:
<section class="col-sm-6 col-md-4">
به این معنا خواهد بود که تا زمانیکه عرض صفحه کمتر از 576px است (sm)، هر آیتم کل عرض صفحه را پوشش می‌دهد. زمانیکه از این break-point رد شدیم، هر آیتم 6 واحد از 12 واحد را به خود اختصاص خواهد داد؛ تا زمانیکه عرض صفحه کمتر از 768px است (md). پس از اینکه این break-point را نیز رد کردیم و اندازه‌ی صفحه بزرگتر از آن شد، اینبار هر آیتم، 4 واحد از 12 واحد را به خود اختصاص می‌دهد:



امکان تغییر موقعیت شروع ستون‌ها در بوت استرپ 4


در تصویر فوق، فرمول تغییر موقعیت شروع ستون‌ها در بوت استرپ 4 را مشاهده می‌کنید. برای مثال اگر offset-sm-1 را به اولین section اضافه کنیم:
<section class="col-sm-6 col-md-4 offset-sm-1">
پس از رد شدن از break-point تعریف شده‌ی sm، اولین section، به اندازه‌ی یک واحد به سمت راست منتقل می‌شود و از لبه‌ی سمت چپ فاصله پیدا می‌کند:


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



کدهای کامل این قسمت را از اینجا می‌توانید دریافت کنید: Bootstrap4_04.zip
اشتراک‌ها
Node.js v15 به همراه npm, v7 منتشر شد

The next version of npm, v7, has been completed and will be shipping with Node.js v15 this week. The new release adds several features requested by developers including support for Workspaces. 

Node.js v15 به همراه npm, v7 منتشر شد
اشتراک‌ها
سایت Learn Entity Framework Core

Entity Framework Core (EF Core) is the latest version of Microsoft's recommended data access technology for applications based on the .NET Core framework. It has been designed to be lightweight, extensible and to support cross platform development. 

سایت Learn Entity Framework Core