NoSQL
- NoSQL ؟
- مروری بر مفاهیم مقدماتی NoSQL
- ردهها و انواع مختلف بانکهای اطلاعاتی NoSQL
- NoSQL و مایکروسافت
- چه زمانی بهتر است از بانکهای اطلاعاتی NoSQL استفاده کرد و چه زمانی خیر؟
- NOSQL قسمت اول
- NOSQL قسمت دوم
- NOSQL قسمت سوم
- آموزش PouchDB : قسمت اول (معرفی)
- آموزش PouchDB : قسمت دوم (شروع به کار)
- آموزش BrightStarDb (قسمت اول)
- پیاده سازی UnitOfWork برای BrightStarDb
- MongoDB #1
- MongoDB #2
- MongoDB #3
- MongoDB #4
- MongoDB #5
- MongoDB #6
- MongoDB #7
- MongoDB #8
- MongoDB #9
- MongoDB #10
- MongoDB #11
- MongoDB #12
- MongoDB #13
- MongoDB #14
- MongoDB #15
بخش دوم: عملیات به روزرسانی، حذف و ایندکس گذاری
بخش سوم: ذخیره و بازیابی فایل
بخش چهارم :Chunk
بخش پنجم : پشتیبانی گیری و بازگردانی
بخش ششم: Import & Export
بخش هفتم : دیتاهای ایستا و پویا
بخش هشتم : الگوی Repository
MDX Query
- آموزش MDX Query - قسمت اول
- آموزش MDX Query - قسمت دوم - نصب و راه اندازی SSAS
- آموزش MDX Query - قسمت سوم - نصب Adventure Work DW و تهیهی پایگاه دادهی Multidimensional Database توسط SSAS
- آموزش MDX Query - قسمت چهارم –آشنایی با AdventureWorksDW2008R2 و آشنایی با محیط BIMS
- آموزش MDX Query - قسمت پنجم – باز کردن یک پایگاه دادهی Multidimensional در محیط BIMS و ساخت یک پروژهی جدید.
- آموزش MDX Query - قسمت ششم – شروع کار با دستورات MDX
- آموزش MDX Query - قسمت هفتم – استفاده از Pivot ، به کارگیری از ساختارهای سلسله مراتبی و به کارگیری Cross Join در کوئری ها
- آموزش MDX Query - قسمت هشتم – کار بر روی ساختارهای سلسله مراتبی
- آموزش MDX Query - قسمت نهم – واکشی اعضا در ساختار سلسله مراتبی دایمنشن ها
- آموزش MDX Query - قسمت دهم – ادامه کار برروی ساختارهای سلسله مراتبی و کار با تابع Cousin و ایجاد Range
- آموزش MDX Query - قسمت یازدهم – استفاده از توابع Lead و Lag
- آموزش MDX Query - قسمت دوازدهم – استفاده از توابع Head , Filter , TopCount , tail
- آموزش MDX Query - قسمت سیزدهم – برخی توابع برای کار روی ساختارهای سلسله مراتبی (prevmember و nextmember)
- آموزش MDX Query - قسمت چهاردهم– Order
- آموزش MDX Query - قسمت پانزدهم – اعمال شرط بر روی خروجی عمل واکشی
- آموزش MDX Query - قسمت شانزدهم – استفاده از تابع Filter در MDX Query ها
- آموزش MDX Query - قسمت هفدهم – توابع Topcount, bottomcount , toppercent, bottompercent, topsum, bottomsum
صورت مساله
public class Product { public int Id { set; get; } public DateTime AddDate { set; get; } public string Name { set; get; } public decimal Price { set; get; } }
میخواهیم زمانیکه فرمهای پویای ویرایش یا افزودن رکوردها ظاهر شدند، در حین تکمیل نام، یک auto complete ظاهر شود:
در حین ورود تاریخ، یک date picker شمسی جهت سهولت ورود اطلاعات نمایش داده شود:
همچنین در قسمت ورود مبلغ و قیمت، به صورت خودکار حرف سه رقم جدا کننده هزارها، نمایش داده شوند تا کاربران در حین ورود مبالغ بالا دچار اشتباه نشوند.
پیشنیازها
- برای نمایش auto complete از همان امکانات توکار jQuery UI که به همراه jqGrid عرضه میشوند، استفاده خواهیم کرد.
- برای نمایش date picker شمسی از مطلب «PersianDatePicker یک DatePicker شمسی به زبان JavaScript که از تاریخ سرور استفاده میکند» کمک خواهیم گرفت.
- جهت اعمال خودکار حرف سه رقم جدا کننده هزارها از افزونهی Price Format جیکوئری استفاده میکنیم.
تعریف و الحاق این پیشنیازها، فایل layout برنامه را به شکل زیر تغییر خواهد داد:
<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>@ViewBag.Title - My ASP.NET Application</title> <link href="~/Content/themes/base/jquery.ui.all.css" rel="stylesheet" /> <link href="~/Content/jquery.jqGrid/ui.jqgrid.css" rel="stylesheet" /> <link href="~/Content/PersianDatePicker.css" rel="stylesheet" /> <link href="~/Content/Site.css" rel="stylesheet" type="text/css" /> </head> <body> <div> @RenderBody() </div> <script src="~/Scripts/jquery-1.7.2.min.js"></script> <script src="~/Scripts/jquery-ui-1.8.11.min.js"></script> <script src="~/Scripts/i18n/grid.locale-fa.js"></script> <script src="~/Scripts/jquery.jqGrid.min.js"></script> <script src="~/Scripts/PersianDatePicker.js"></script> <script src="~/Scripts/jquery.price_format.2.0.js"></script> @RenderSection("Scripts", required: false) </body> </html>
تغییرات مورد نیاز سمت کلاینت، جهت اعمال افزونههای جیکوئری و سفارشی سازی عناصر دریافت اطلاعات
الف) نمایش auto complete در حین ورود نام محصولات
colModel: [ { name: 'Name', index: 'Name', align: 'right', width: 100, editable: true, edittype: 'text', editoptions: { maxlength: 40, dataInit: function (elem) { // http://jqueryui.com/autocomplete/ $(elem).autocomplete({ source: '@Url.Action("GetProductNames","Home")', minLength: 2, select: function (event, ui) { $(elem).val(ui.item.value); $(elem).trigger('change'); } }); } }, editrules: { required: true } } ],
برای پردازش سمت سرور آن و مقدار دهی url آن، یک چنین اکشن متدی را میتوان تدارک دید:
public ActionResult GetProductNames(string term) { var list = ProductDataSource.LatestProducts .Where(x => x.Name.StartsWith(term)) .Select(x => x.Name) .Take(10) .ToArray(); return Json(list, JsonRequestBehavior.AllowGet); }
ب) نمایش date picker شمسی در حین ورود تاریخ
colModel: [ { name: 'AddDate', index: 'AddDate', align: 'center', width: 100, editable: true, edittype: 'text', editoptions: { maxlength: 10, // https://www.dntips.ir/post/1382 onclick: "PersianDatePicker.Show(this,'@today');" }, editrules: { required: true } } ],
@{ ViewBag.Title = "Index"; var today = DateTime.Now.ToPersianDate(); }
ج) اعمال حروف سه رقم جدا کننده هزارها در حین ورود قیمت
colModel: [ { name: 'Price', index: 'Price', align: 'center', width: 100, formatter: 'currency', formatoptions: { decimalSeparator: '.', thousandsSeparator: ',', decimalPlaces: 2, prefix: '$' }, editable: true, edittype: 'text', editoptions: { dir: 'ltr', dataInit: function (elem) { // http://jquerypriceformat.com/ $(elem).priceFormat({ prefix: '', thousandsSeparator: ',', clearPrefix: true, centsSeparator: '', centsLimit: 0 }); } }, editrules: { required: true, minValue: 0 } } ],
یک نکته
همین تعاریف را دقیقا به فرمهای جستجو نیز میتوان اعمال کرد. در اینجا برای حالات ویرایش و افزودن رکوردها، editoptions مقدار دهی شدهاست؛ در مورد فرمهای جستجو باید searchoptions و برای مثال dataInit آنرا مقدار دهی کرد.
مشکل مهم!
با تنظیمات فوق، قسمت UI بدون مشکل کار میکند. اما اگر در سمت سرور، مقادیر دریافتی را بررسی کنیم، نه تاریخ و نه قیمت، قابل دریافت نیستند. زیرا تاریخ ارسالی به سرور شمسی است و مدل برنامه DateTime میلادی میباشد. همچنین به دلیل وجود حروف سه رقم جدا کننده هزارها، عبارت دریافتی قابل تبدیل به عدد نیستند و مقدار دریافتی صفر خواهد بود.
برای رفع این مشکلات، نیاز به تغییر model binder توکار ASP.NET MVC است. برای تاریخها از کلاس PersianDateModelBinder میتوان استفاده کرد. برای اعداد decimal از کلاس ذیل:
using System; using System.Globalization; using System.Threading; using System.Web.Mvc; namespace jqGrid05.CustomModelBinders { /// <summary> /// How to register it in the Application_Start method of Global.asax.cs /// ModelBinders.Binders.Add(typeof(decimal), new DecimalBinder()); /// </summary> public class DecimalBinder : DefaultModelBinder { public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext) { if (bindingContext.ModelType == typeof(decimal) || bindingContext.ModelType == typeof(decimal?)) { return bindDecimal(bindingContext); } return base.BindModel(controllerContext, bindingContext); } private static object bindDecimal(ModelBindingContext bindingContext) { var valueProviderResult = bindingContext.ValueProvider.GetValue(bindingContext.ModelName); if (valueProviderResult == null) return null; bindingContext.ModelState.SetModelValue(bindingContext.ModelName, valueProviderResult); decimal value; var valueAsString = valueProviderResult.AttemptedValue == null ? null : valueProviderResult.AttemptedValue.Trim(); if (string.IsNullOrEmpty(valueAsString)) return null; if (!decimal.TryParse(valueAsString, NumberStyles.Any, Thread.CurrentThread.CurrentCulture, out value)) { const string error ="عدد وارد شده معتبر نیست"; var ex = new InvalidOperationException(error, new Exception(error, new FormatException(error))); bindingContext.ModelState.AddModelError(bindingContext.ModelName, ex); return null; } return value; } } }
برای ثبت و معرفی این کلاسها باید به نحو ذیل در فایل global.asax.cs برنامه عمل کرد:
using System; using System.Web.Mvc; using System.Web.Routing; using jqGrid05.CustomModelBinders; namespace jqGrid05 { public class MvcApplication : System.Web.HttpApplication { protected void Application_Start() { AreaRegistration.RegisterAllAreas(); RouteConfig.RegisterRoutes(RouteTable.Routes); ModelBinders.Binders.Add(typeof(DateTime), new PersianDateModelBinder()); ModelBinders.Binders.Add(typeof(decimal), new DecimalBinder()); } } }
کدهای کامل این مثال را از اینجا میتوانید دریافت کنید
jqGrid05.zip
سیستمهای توزیع شده در NET.
تاریخچهی تغییرات کامپوننت Date-Picker
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); } }
پس از تعریف 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 { }
پس از آن اگر 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; }
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"); }
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'); }
در این تصویر روزهای خاکستری، قابل انتخاب نیستند و غیرفعال شدهاند (چون 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; } }
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); } }
در اینجا، onInput، با ورود دستی اطلاعات به textbox کامپوننت، فعال میشود و onChange، در صورت انتخاب یک تاریخ از تقویم.
کدهای کامل این مثال را از اینجا میتوانید دریافت کنید.
* نکته: پروژه انگیولار متریال ۲ در زمان نوشتن این مقاله به تازگی نسخه بتا ۵ را ارائه داده و همچنان در حال توسعه است. این بدان معنی است که ممکن است همه چیز به سرعت تغییر یابد.
مقدمه
انگیولار متریال ۲ همانند انگیولار متریال یک، تمامی المانهای مورد نیاز برای طراحی یک برنامه تک صفحهای را به راحتی فراهم میکند (هرچند تمامی المانهای آن در نسخه بتا پیاده سازی نشدهاند). خبر خوب اینکه، اکثر کامپوننتهای ارائه شده در انگیولار متریال ۲ از قالب راست به چپ پشتیبانی میکنند و اعمال این قالب به سادگی اضافه کردن خصوصیت dir یک المان به rtl است.
در صفحه گیتهاب انگیولار متریال ۲ آمدهاست که انگیولار متریال ۲، واسطهای کاربری با کیفیت بالا را ارائه میدهد و در ادامه منظورش را از «کیفیت بالا»، اینگونه بیان میکند:
- بینالمللی
و قابل دسترس برای همه به نحوی که تمامی کاربران میتوانند از آنها استفاده کنند
(عدم مشکل در چند زبانه بودن و پشتیبانی از قالب راست به چپ و چپ به راست) .
- دارای APIهای ساده برای توسعه دهندگان.
- رفتار مورد انتظار و بدون خطا در تمامی موردهای کاری
-
تست تمامی رفتارها توسط تست یکپارچگی (unit test ) و تست واحد ( integration test )
-
قابلیت سفارشی سازی در چارچوب طراحی متریال
-
بهرهوری بالا
-
کد تمیز و مستندات خوب
شروع کار با انگیولار متریال ۲
قدم اول: نصب angular-material و hammerjs
برای شروع بایستی Angular Material و angular animations و hammer.js را توسط npm به صورت زیر نصب کنید.
npm install --save @angular/material @angular/animations
npm install --save hammerjs
angular/material@: بسته مربوط به انگیولار متریال دو را نصب خواهد کرد.
angular/animations@: این بسته امکاناتی جهت ساخت افکتهای ویژه هنگام تغییر صفحات، یا بارگذاری المنتها را از طریق کدهای css نوشته شده، به راحتی امکانپذیر میکند.
Hammerjs: برخی از کامپوننتهای موجود در انگیولار متریال ۲ وابسته به کتابخانه Hammerjs هستند. (از جمله md-slide-toggle و md-slider, mdTooltip)
قدم دوم: معرفی کتابخانههای خارجی به angular-cli.json
"scripts": [ "../node_modules/hammerjs/hammer.min.js" ],
قدم سوم: افزودن Angular Material به ماوژل اصلی برنامه انگیولار
import { BrowserModule } from '@angular/platform-browser'; import { NgModule } from '@angular/core'; import { FormsModule } from '@angular/forms'; import { HttpModule } from '@angular/http'; import { MaterialModule } from '@angular/material'; import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; import { AppComponent } from './app.component'; @NgModule({ declarations: [ AppComponent ], imports: [ BrowserModule, FormsModule, HttpModule, MaterialModule, BrowserAnimationsModule ], providers: [], bootstrap: [AppComponent] }) export class AppModule { }
قدم چهارم: افزودن تم و آیکون
همراه با نصب Angular Material تعدادی تم از قبل ساخته شده نیز نصب خواهند شد که شامل یکسری استایل با رنگهای مشخصی هستند. از جمله این تمها عبارتند از:
- indigo-pink
- deeppurple-amber
- purple-green
- pink-bluegrey
همچنین با استفاده از Material Design icons نیز با استفاده از تگ <md-icon> به آیکونهای متریال نیز میتوان دسترسی داشت.
برای افزودن آیکونهای متریال و همچنین انتخاب یک تم از قبل ساخته شده دو خط زیر را به فایل style.css اصلی برنامه اضافه کنید.
@import '~https://fonts.googleapis.com/icon?family=Material+Icons'; @import '~@angular/material/prebuilt-themes/deeppurple-amber.css';
نکتهای که در تگ <md-icon> وجود دارد این است که این تگ انواع فونتها و آیکونهای svg را نیز پشتیبانی میکند. استفاده از آیکونهای متریال یکی از قابلیتهای این تگ محسوب میشود.
برای اطلاعات بیشتر از نحوه ساخت تم سفارشی میتوانید این لینک را دنبال کنید.
قدم آخر: انگیولار متریال آماده است!
با انجام مراحل بالا اکنون میتوانید به راحتی از کامپوننتهای متریال استفاده کنید. کافی است کدهای زیر را به فایل app.component.html اضافه کنید و یک قالب ساده برای برنامه خود بسازید.
<md-sidenav-container> <md-sidenav #end align="end" opened="true" mode="side"> <md-toolbar color="accent"> <div> <md-toolbar-row> <img src="https://material.angular.io/favicon.ico" style="height:50px;margin-top: 2px; margin-bottom: 2px;"> <span> برنامه من </span> </md-toolbar-row> </div> </md-toolbar> <md-nav-list> <md-list-item [routerLink]="['/']"> <div> <div></div> <md-icon role="img" aria-label="home">home</md-icon> <span>خانه</span> </div> </md-list-item> </md-nav-list> <md-nav-list> <md-list-item [routerLink]="['/registries']"> <div> <div></div> <md-icon role="img" aria-label="forms">content_paste</md-icon> <span>فرم</span> </div> </md-list-item> </md-nav-list> <md-nav-list> <md-list-item href="/charts"> <div> <div></div> <md-icon role="img" aria-label="charts">show_chart</md-icon> <span>نمودارها</span> </div> </md-list-item> </md-nav-list> </md-sidenav> <header> <md-toolbar color="primary"> <button md-icon-button (click)="end.toggle()"> <md-icon>menu</md-icon> </button> <span>داشبورد</span> <button md-icon-button [md-menu-trigger-for]="menu"> <md-icon>person</md-icon> </button> </md-toolbar> <md-menu x-position="before" #menu="mdMenu"> <button md-menu-item>تنظیمات</button> <button md-menu-item>خروج</button> </md-menu> </header> <main> <router-outlet></router-outlet> </main> </md-sidenav-container> <span> <button md-fab> <md-icon>check circle</md-icon> </button> </span>
همچنین کدهای css زیر را به فایل اصلی style.css اضافه کنید.
html, body, material-app, md-sidenav-container, .my-content { margin: 0; direction: rtl; width: 100%; height: 100%; } .mat-button-toggle, .mat-button-base, .mat-button, .mat-raised-button, .mat-fab, .mat-icon-button, .mat-mini-fab, .mat-card, .mat-checkbox, .mat-input-container, .mat-list, .mat-menu-item, .mat-radio-button, .mat-select, .mat-list .mat-list-item .mat-list-item-content, .mat-nav-list .mat-list-item .mat-list-item-content, .mat-simple-snackbar, .mat-tab-label, .mat-slide-toggle-content, .mat-toolbar, .mat-tooltip { font-family: 'Iranian Sans', Tahoma !important; } md-sidenav { width: 225px; max-width: 70%; } md-sidenav md-nav-list { display: block; } md-sidenav md-nav-list :hover { background-color: rgb(250, 250, 250); } md-sidenav md-nav-list .md-list-item { cursor: pointer; } .side-navigation { padding-top: 0; } md-nav-list.side-navigation a[md-list-item] > .md-list-item > span.title { margin-right: 10px; } md-nav-list.side-navigation a[md-list-item] > .md-list-item { -webkit-font-smoothing: antialiased; letter-spacing: .14px; } md-list a[md-list-item] .md-list-item, md-list md-list-item .md-list-item, md-nav-list a[md-list-item] .md-list-item, md-nav-list md-list-item .md-list-item { display: flex; flex-direction: row; align-items: center; box-sizing: border-box; height: 48px; padding: 0 16px; } button.my-fab { position: absolute; right: 20px; bottom: 10px; } md-card { margin: 1em; } md-toolbar-row { justify-content: space-between; } .done { position: fixed; bottom: 20px; left: 20px; color: white; } md-nav-list.side-navigation a[md-list-item] { position: relative; } md-list a[md-list-item], md-list md-list-item, md-nav-list a[md-list-item], md-nav-list md-list-item { display: block; } md-list a[md-list-item], md-list md-list-item, md-nav-list a[md-list-item], md-nav-list md-list-item { color: #000; } md-nav-list a { text-decoration: none; color: inherit; } a { color: #039be5; text-decoration: none; -webkit-tap-highlight-color: transparent; } .no-padding { padding: 0 !important; }
به همین راحتی برنامه نمونه با طراحی متریال آماده است.