@model IEnumerable<FsWeb.Models.Book> <!DOCTYPE html> <html> <head> <title>@ViewBag.Title</title> <meta name="viewport" content="width=device-width, initial-scale=1" /> <link rel="stylesheet" href="http://code.jquery.com/mobile/1.0.1/jquery.mobile-1.0.1.min.css" /> </head> <body> <div data-role="page" data-theme="a" id="booksPage"> <div data-role="header"> <h1>Guitars</h1> </div> <div data-role="content"> <ul data-role="listview" data-filter="true" data-inset="true"> @foreach(var x in Model) { <li><a href="#">@x.Name</a></li> } </ul> </div> </div> <script src="http://code.jquery.com/jquery-1.6.4.min.js"> </script> <script src="http://code.jquery.com/mobile/1.0.1/jquery.mobile-1.0.1.min.js"> </script> <script> $(document).delegate("#bookPage", 'pageshow', function (event) { $("div:jqmData(role='content') > ul").listview('refresh'); }); </script> </body> </html>
برای ساخت کنترلر جدید، در پروژه #F ساخته شده یک Source File ایجاد نمایید و کدهای زیر را در آن کپی نمایید:
namespace FsWeb.Controllers open System.Web.Mvc open FsWeb.Models [<HandleError>] type BooksController() = inherit Controller() member this.Index () = seq { yield Book(Name = "My F# Book") yield Book(Name = "My C# Book") } |> this.View
اما نکته ای که در مثال بالا وجود دارد این است که دو نمونه از نوع Book را برای ساخت seq وهله سازی میکند. در نتیجه باید Book Type را به عنوان مدل تعریف کنیم. به صورت زیر:
namespace FsWeb.Models type Book = { Id : Guid; Name : string }
namespace FsWeb.Models type Book() = member val Name = "" with get, set
اگر همچون پروژههای #C قصد دارید با استفاده از Attributeها مدل خود را اعتبارسنجی نمایید میتوانید به صورت زیر اقدام نمایید:
open System.ComponentModel.DataAnnotations type Book() = [<Required>] member val Name = "" with get, set
namespace FsWeb.Models open System open System.ComponentModel.DataAnnotations type Book() = [<Key>] member val Id = Guid.NewGuid() with get, set [<Required>] member val Name = "" with get, set
نکته: دستور open معادل با using در #C است.
A set of files that comprise a standalone app, a library, or a set of end-to-end (e2e) tests.
ng --version
ng new angular-apps --create-application=false
angular-apps/README.md angular-apps/angular.json angular-apps/package.json angular-apps/tsconfig.json angular-apps/tslint.json angular-apps/.editorconfig angular-apps/.gitignore
cd angular-apps
ng generate application admin
ng generate library ngx-qrcode
ng generate service auth --project=admin
projects/admin/src/app/auth.service.spec.ts projects/admin/src/app/auth.service.ts
ng serve admin
ng new
What name would you like to use for the new workspace and initial project?
با استفاده از پارامترهای آبشاری میتوان شیءای را در اختیار تمام کامپوننتهای قرار گرفته شدهی در سلسله مراتب آنها قرار داد. برای مثال اگر در فایل Client\Shared\MainLayout.razor، جائیکه سایر کامپوننتها قرار است رندر شوند را توسط یک کامپوننت سطح بالا محصور کنیم:
<Alert> @Body </Alert>
بنابراین طراحی سادهی کامپوننت Alert ای (Client\Shared\Alert.razor) که تامین کنندهی یک پارامتر آبشاری سراسری است، به صورت زیر میتواند باشد:
<CascadingValue Value=this> @if(IsVisible) { <div class="alert @Css" role="alert"> @Message <button type="button" class="close" data-dismiss="alert" aria-label="Close" @onclick="HideAlert"> <span aria-hidden="true">×</span> </button> </div> } @ChildContent </CascadingValue> @code { [Parameter] public RenderFragment ChildContent { get; set; } private bool IsVisible; private string Message; private string Css = "alert-primary"; public void ShowAlert(string message, AlertType alertType) { IsVisible = true; Message = message; Css = alertType switch { AlertType.Success => "alert-success", AlertType.Info => "alert-primary", AlertType.Danger => "alert-danger", AlertType.Warning => "alert-warning", _ => "alert-primary" }; StateHasChanged(); } public void HideAlert() { IsVisible = false; } }
namespace BlazorWasmAlert.Client.Shared { public enum AlertType { Success, Info, Danger, Warning } }
الف) وجود یک CascadingValue که اینبار Value آن به خود کامپوننت اشاره میکند (Value=this). یعنی پارامتر آبشاری که در اختیار سایر کامپوننتهای محصور شدهی توسط آن ارسال میشود، دقیقا وهلهای از کامپوننت Alert است که توسط آن میتوان برای مثال، متد عمومی ShowAlert آنرا فراخوانی کرد:
<CascadingValue Value=this>
پس از درج این کامپوننت در فایل layout، روش استفادهی از آن برای مثال در کامپوننت Index به صورت زیر است:
@page "/" <h1>Hello, world!</h1> <button class="btn btn-primary" @onclick="ShowAlert">Show Alert!</button> @code { [CascadingParameter] public Alert Alert { get; set; } private void ShowAlert() { Alert.ShowAlert("This is a test!", AlertType.Info); } }
پ.ن.
در طراحی Blazor، از طراحی React الهام گرفته شدهاست و CascadingValue آن دقیقا معادل Context API جدید React است.
کامپوننتهای jQuery زیادی وجود دارند که توسط آنها میتوان تصاویر را بصورت زمانبندی شده و به همراه افکتهای زیبا در سایت خود نشان داد. مانند اینجا .
در این قصد ایجاد helper برای کامپوننت NivoSlider را داریم.
1- یک پروژه Asp.net Mvc 4.0 ایجاد میکنیم.
2- سپس فایل jquery.nivo.slider.pack.js ، فایلهای css مربوط به این کامپوننت و چهار تم موجود را از سایت این کامپوننت و یا درون سورس مثال ارائه شده دریافت میکنیم.
3- به کلاس BundleConfig رفته و کدهای زیر را اضافه میکنیم:
#region Nivo Slider bundles.Add(new StyleBundle("~/Content/NivoSlider").Include("~/Content/nivoSlider/nivo-slider.css")); bundles.Add(new StyleBundle("~/Content/NivoSliderDefaultTheme").Include("~/Content/nivoSlider/themes/default/default.css")); bundles.Add(new StyleBundle("~/Content/NivoSliderDarkTheme").Include("~/Content/nivoSlider/themes/dark/dark.css")); bundles.Add(new StyleBundle("~/Content/NivoSliderLightTheme").Include("~/Content/nivoSlider/themes/light/light.css")); bundles.Add(new StyleBundle("~/Content/NivoSliderBarTheme").Include("~/Content/nivoSlider/themes/bar/bar.css")); bundles.Add(new ScriptBundle("~/bundles/NivoSlider").Include("~/Scripts/jquery.nivo.slider.pack.js")); #endregion
سپس در فایل shared آنها را بصورت زیر اعمال میکنیم:
<!DOCTYPE html> <html> <head> <title>@ViewBag.Title</title> <script type="text/javascript" src="~/Scripts/jquery-1.9.1.min.js"></script> @Styles.Render("~/Content/NivoSlider", "~/Content/NivoSliderDefaultTheme","~/Content/NivoSliderLightTheme") @Scripts.Render("~/bundles/NivoSlider") </head> <body> @RenderBody() @RenderSection("scripts", required: false) </body> </html>
4- یک پوشه با عنوان helper به پروژه اضافه میکنیم. سپس کلاسهای زیر را به آن اضافه میکنیم :
public class NivoSliderHelper { #region Fields private string _id = "nivo1"; private List<NivoSliderItem> _models = null; private string _width = "100%"; private NivoSliderTheme _theme = NivoSliderTheme.Default; private string _effect = "random"; // Specify sets like= 'fold;fade;sliceDown' private int _slices = 15; // For slice animations private int _boxCols = 8; // For box animations private int _boxRows = 4; // For box animations private int _animSpeed = 500; // Slide transition speed private int _pauseTime = 3000; // How long each slide will show private int _startSlide = 0; // Set starting Slide (0 index) private bool _directionNav = true; // Next & Prev navigation private bool _controlNav = true; // 1;2;3... navigation private bool _controlNavThumbs = false; // Use thumbnails for Control Nav private bool _pauseOnHover = true; // Stop animation while hovering private bool _manualAdvance = false; // Force manual transitions private string _prevText = "Prev"; // Prev directionNav text private string _nextText = "Next"; // Next directionNav text private bool _randomStart = false; // Start on a random slide private string _beforeChange = ""; // Triggers before a slide transition private string _afterChange = ""; // Triggers after a slide transition private string _slideshowEnd = ""; // Triggers after all slides have been shown private string _lastSlide = ""; // Triggers when last slide is shown private string _afterLoad = ""; #endregion string makeParameters() { var builder = new StringBuilder(); builder.Append("{"); builder.Append(string.Format("effect:'{0}'", _effect)); builder.AppendLine(string.Format(",slices:{0}", _slices)); builder.AppendLine(string.Format(",boxCols:{0}", _boxCols)); builder.AppendLine(string.Format(",boxRows:{0}", _boxRows)); builder.AppendLine(string.Format(",animSpeed:{0}", _animSpeed)); builder.AppendLine(string.Format(",pauseTime:{0}", _pauseTime)); builder.AppendLine(string.Format(",startSlide:{0}", _startSlide)); builder.AppendLine(string.Format(",directionNav:{0}", _directionNav.ToString().ToLower())); builder.AppendLine(string.Format(",controlNav:{0}", _controlNav.ToString().ToLower())); builder.AppendLine(string.Format(",controlNavThumbs:{0}", _controlNavThumbs.ToString().ToLower())); builder.AppendLine(string.Format(",pauseOnHover:{0}", _pauseOnHover.ToString().ToLower())); builder.AppendLine(string.Format(",manualAdvance:{0}", _manualAdvance.ToString().ToLower())); builder.AppendLine(string.Format(",prevText:'{0}'", _prevText)); builder.AppendLine(string.Format(",nextText:'{0}'", _nextText)); builder.AppendLine(string.Format(",randomStart:{0}", _randomStart.ToString().ToLower())); builder.AppendLine(string.Format(",beforeChange:{0}", _beforeChange)); builder.AppendLine(string.Format(",afterChange:{0}", _afterChange)); builder.AppendLine(string.Format(",slideshowEnd:{0}", _slideshowEnd)); builder.AppendLine(string.Format(",lastSlide:{0}", _lastSlide)); builder.AppendLine(string.Format(",afterLoad:{0}", _afterLoad)); builder.Append("}"); return builder.ToString(); } public NivoSliderHelper ( string id, List<NivoSliderItem> models, string width = "100%", NivoSliderTheme theme = NivoSliderTheme.Default, string effect = "random", int slices = 15, int boxCols = 8, int boxRows = 4, int animSpeed = 500, int pauseTime = 3000, int startSlide = 0, bool directionNav = true, bool controlNav = true, bool controlNavThumbs = false, bool pauseOnHover = true, bool manualAdvance = false, string prevText = "Prev", string nextText = "Next", bool randomStart = false, string beforeChange = "function(){}", string afterChange = "function(){}", string slideshowEnd = "function(){}", string lastSlide = "function(){}", string afterLoad = "function(){}") { _id = id; _models = models; _width = width; _theme = theme; _effect = effect; _slices = slices; _boxCols = boxCols; _boxRows = boxRows; _animSpeed = animSpeed; _pauseTime = pauseTime; _startSlide = startSlide; _directionNav = directionNav; _controlNav = controlNav; _controlNavThumbs = controlNavThumbs; _pauseOnHover = pauseOnHover; _manualAdvance = manualAdvance; _prevText = prevText; _nextText = nextText; _randomStart = randomStart; _beforeChange = beforeChange; _afterChange = afterChange; _slideshowEnd = slideshowEnd; _lastSlide = lastSlide; _afterLoad = afterLoad; } public IHtmlString GetHtml() { var thm = "theme-" + _theme.ToString().ToLower(); var sb = new StringBuilder(); sb.AppendLine("<div style='width:" + _width + ";height:auto;margin:0px auto' class='" + thm + "'>"); sb.AppendLine("<div id='" + _id + "' class='nivoSlider'>"); foreach (var model in _models) { string img = string.Format("<img src='{0}' alt='{1}' title='{2}' />", model.ImageFilePath, "", model.Caption); string item = ""; if (model.LinkUrl.Trim().Length > 0 && Uri.IsWellFormedUriString(model.LinkUrl, UriKind.RelativeOrAbsolute)) { item = string.Format("<a href='{0}'>{1}</a>", model.LinkUrl, img); } else { item = img; } sb.AppendLine(item); } sb.AppendLine("</div>"); sb.AppendLine("</div>"); sb.AppendLine("<script type='text/javascript'>"); //sb.AppendLine("$('#" + _id + "').parent().ready(function () {"); sb.Append("$(document).ready(function(){"); sb.AppendLine("$('#" + _id + "').nivoSlider(" + makeParameters() + ");"); //sb.AppendLine("$('.nivo-controlNav a').empty();");//semi hack for rtl layout //sb.AppendLine("$('#" + _id + "').nivoSlider();"); sb.AppendLine("});"); sb.AppendLine("</script>"); return new HtmlString(sb.ToString()); } }
public enum NivoSliderTheme { Default, Light, Dark, Bar, }
public class NivoSliderItem { public string ImageFilePath { get; set; } public string Caption { get; set; } public string LinkUrl { get; set; } }
public class HomeController : Controller { public ActionResult Index() { return View(); } public virtual ActionResult NivoSlider() { var models = new List<NivoSliderItem> { new NivoSliderItem() { ImageFilePath =Url.Content("~/Images/img1.jpg"), Caption = "عنوان اول", LinkUrl = "http://www.google.com", }, new NivoSliderItem() { ImageFilePath =Url.Content("~/Images/img2.jpg"), Caption = "#htmlcaption", LinkUrl = "", }, new NivoSliderItem() { ImageFilePath =Url.Content("~/Images/img3.jpg"), Caption = "عنوان سوم", LinkUrl = "", }, new NivoSliderItem() { ImageFilePath =Url.Content("~/Images/img4.jpg"), Caption = "عنوان چهارم", LinkUrl = "", }, new NivoSliderItem() { ImageFilePath =Url.Content("~/Images/img5.jpg"), Caption = "عنوان پنجم", LinkUrl = "", } }; return PartialView("_NivoSlider", models); } }
@{ ViewBag.Title = "Index"; } <h2>Nivo Slider Index</h2> @{ Html.RenderAction("NivoSlider", "Home");}
@using NivoSlider.Helper @model List<NivoSliderItem> @{ var nivo1 = new NivoSliderHelper("nivo1", Model.Skip(0).Take(3).ToList(), theme: NivoSliderTheme.Default, width: "500px"); var nivo2 = new NivoSliderHelper("nivo2", Model.Skip(3).Take(2).ToList(), theme: NivoSliderTheme.Light, width: "500px"); } @nivo1.GetHtml() <div id="htmlcaption"> <strong>This</strong> is an example of a <em>HTML</em> caption with <a href="#">a link</a>. </div> <br /> <br /> @nivo2.GetHtml()
Dart کتابخانه ای است که توسط شرکت گوگل ارائه شده است و گفته میشود، قرار است جایگزین جاوا اسکریپت گردد و از آدرس https://www.dartlang.org قابل دسترسی میباشد. این کتابخانه، دارای انعطاف پذیری فوق العاده بالایی است و کد نویسی Java Script را راحتتر میکند. در حال حاضر هیچ مرورگری به غیر از Chromium از این تکنولوژی پشتیبانی نمیکند و جهت تسهیل در کدنویسی، باید از ویرایشگر Dart Editor استفاده کنید. این ویرایشگر کدهای نوشته شده را به دو صورت Native و JavaScript Compiled در اختیار مرورگر قرار میدهد. در ادامه با نحوهی کار و راه اندازی Dart آشنا خواهید شد.
ابتدا Dart و ویرایشگر مربوط به آن را توسط لینکهای زیر دانلود کنید:
دانلود نسخه 64 بیتی دارت + ویرایشگر
دانلود نسخه 32 بیتی دارت + ویرایشگر
بعد از اینکه فایلهای فوق را از حالت فشرده خارج کردید، پوشه ای با نام dart ایجاد مینماید. وارد پوشه dart شده و DartEditor را اجرا کنید.
توجه: جهت اجرای dart به JDK 6.0 یا بالاتر نیاز دارید
در مرحله بعد نمونه کدهای Dart را از لینک زیر دانلود نمایید و از حالت فشرده خارج کنید. پوشه ای با نام one-hour-codelab ایجاد میگردد.
از منوی File > Open Existing Folder… پوشه one-hour-codelab را باز کنید .
توضیحات
- پوشه packages و همچنین فایلهای pubspec.yaml و pubspec.lock شامل پیش نیازها و Package هایی هستند که جهت اجرای برنامههای تحت Dart مورد نیاز هستند. Dart Editor این نیازمندیها را به صورت خودکار نصب و تنظیم میکند.
توجه: اگر پوشه Packages را مشاهده نکردید و یا در سمت چپ فایلها علامت X قرمز رنگ وجود داشت، بدین معنی است که package ها به درستی نصب نشده اند. برای این منظور بر روی pubspec.yaml کلیک راست نموده و گزینه Get Pub را انتخاب کنید. توجه داشته باید که بدلیل تحریم ایران توسط گوگل باید از ابزارهای عبور از تحریم استفاده کنید.
- 6 پوشه را نیز در تصویر فوق مشاهده میکنید که نمونه کد piratebadge را بصورت مرحله به مرحله انجام داده و به پایان میرساند.
- Dart SDK شامل سورس کد مربوط به تمامی توابع، متغیرها و کلاس هایی است که توسط کیت توسعه نرم افزاری Dart ارائه شده است.
- Installed Packages شامل سورس کد مربوط به تمامی توابع، متغیرها و کلاسهای کتابخانههای اضافهتری است که Application به آنها وابسته است.
گام اول: اجرای یک برنامه کوچک
در این مرحله سورس کدهای آماده را مشاهده میکنید و با ساختار کدهای Dart و HTML آشنا میشوید و برنامه کوچکی را اجرا مینمایید.
در Dart Editor پوشه 1-blankbadge را باز کنید و فایلهای piratebadge.html و piratebadge.dart را مشاهده نمایید.
کد موجود در فایل piratebadge.html
<html> <head> <meta charset="utf-8"> <title>Pirate badge</title> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <link rel="stylesheet" href="piratebadge.css"> </head> <body> <h1>Pirate badge</h1> <div> TO DO: Put the UI widgets here. </div> <div> <div> Arrr! Me name is </div> <div> <span id="badgeName"> </span> </div> </div> <script type="application/dart" src="piratebadge.dart"></script> <script src="packages/browser/dart.js"></script> </body> </html>
توضیحات
- در کد HTML ، اولین تگ <script> ، فایل piratebadge.dart را جهت پیاده سازی دستورات dart به صفحه ضمیمه مینماید
- Dart Virtual Machine (Dart VM) کدهای Dart را بصورت Native یا بومی ماشین اجرا میکند. Dart VM کدهای خود را در Dartium که یک ویرایش ویژه از مرورگر Chromium میباشد اجرا میکند که میتواند برنامههای تحت Dart را بصورت Native اجرا کند.
- فایل packages/browser/dart.js پشتیبانی مرورگر از کد Native دارت را بررسی میکند و در صورت پشتیبانی، Dart VM را راه اندازی میکند و در غیر این صورت JavaScript کامپایل شده را بارگزاری مینماید.
کد موجود در piratebadge.dart
void main() { // Your app starts here. }
- این فایل شامل تابع main میباشد که تنها نقطه ورود به application است. تگ <script> موجود در piratebadge.html برنامه را با فراخوانی این تابع راه اندازی میکند.
- تابع main() یک تابع سطح بالا یا top-level میباشد.
- متغیرها و توابع top-level عناصری هستند که خارج از ساختار تعریف کلاس ایجاد میشوند.
جهت اجرای برنامه در Dart Editor بر روی piratebadge.html کلیک راست نمایید و گزینه Run in Dartium را اجرا کنید. این فایل توسط Dartium اجرا میشود و تابع main() را فراخوانی میکند و صفحه ای همانند شکل زیر را نمایش میدهد.
گام دوم: افزودن فیلد input
توجه داشته باشید که در این مرحله یا میتوانید تغییرات مورد نظر خود را در طی آموزش بر روی پوشهی 1-blankbadge اعمال کنید و یا به پوشههای تهیه شده در نمونه کد موجود در همین پروژه مراجعه نمایید.
در این مرحله یک تگ <input> به تگ <div class=”widgets”> اضافه کنید.
... <div> <div> <input type="text" id="inputName" maxlength="15"> </div> </div> ...
سپس کتابخانه dart:html را به ابتدای فایل piratebadge.dart اضافه کنید.
import 'dart:html';
توضیحات
- دستور فوق کلاسها و Resource های موجود در کتابخانه dart:html را اضافه میکند.
- از حجیم شدن کدهای خود نگران نباشید، زیرا فرایند کامپایل کدهای اضافی را حذف خواهد کرد.
- کتابخانه dart:html شامل کلاسهایی جهت کار با عناصر DOM و توابعی جهت دسترسی به این عناصر میباشد.
- در مباحث بعدی یاد میگیرید که با استفاده از کلمه کلیدی show فقط کلاسهایی را import کنید که به آن نیاز دارید.
- اگر کتابخانه ای در هیچ بخش کد استفاده نشود، خود Dart Editor به صورت warning اخطار میدهد و میتوانید آن را حذف کنید.
دستور زیر را در تابع main بنویسید تا رویداد مربوط به ورود اطلاعات در فیلد input را مدیریت نمایید.
void main() { querySelector('#inputName').onInput.listen(updateBadge); }
توضیحات
- تابع querySelector() در کتابخانه dart:html تعریف شده است و یک المنت DOM را جستجو مینماید. پارامتر ورودی آن یک selector میباشد که در اینجا فیلد input را توسط #inputName جستجو نمودیم که یک ID Selector میباشد.
- نوع خروجی این متد یک شی از نوع DOM میباشد.
- تابع onInput.Listen() رویدادی را برای پاسخگویی به ورود اطلاعات در فیلد input تعریف میکند. زمانی که کاربر اطلاعاتی را وارد نماید، تابع updateBadge فراخوانی میگردد.
- رویداد input زمانی رخ میدهد که کاربر کلیدی را از صفحه کلید فشار دهد.
- رشتهها همانند جاوا اسکریپت میتوانند در " یا ' قرار بگیرند.
تابع زیر را به صورت top-level یعنی خارج از تابع main تعریف کنید.
... void updateBadge(Event e) { querySelector('#badgeName').text = e.target.value; }
توضیحات
- این تابع محتوای المنت badgeName را به محتوای وارد شده در فیلد input تغییر میدهد.
- پارامتر ورودی این تابع شی e از نوع Event میباشد و به همین دلیل میتوانیم این تابع را یک Event Handler بنامیم.
- e.target به شی ای اشاره میکند که موجب رخداد رویداد شده است و در اینجا همان فیلد input میباشد
- با نوشتن کد فوق یک warning را مشاهده میکنید که بیان میکند ممکن است خصوصیت value برای e.target وجود نداشته باشد. برای حل این مسئله کد را بصورت زیر تغییر دهید.
... void updateBadge(Event e) { querySelector('#badgeName').text = (e.target as InputElement).value; }
توضیحات
- کلمه کلیدی as به منظور تبدیل نوع استفاده میشود که e.target را به یک InputElement تبدیل میکند.
همانند گام اول برنامه را اجرا کنید و نتیجه را مشاهده نمایید. با تایپ کردن در فیلد input به صورت همزمان در کادر قرمز رنگ نیز نتیجه تایپ را مشاهده مینمایید.
new Vue({ // state // دادهها در اینجا قرار میگیرند data () { return { count: 0 } }, // view // ویوها برای نمایش دادهها مورد استفاده قرار میگیرند template: `<div>{{ count }}</div>`, // actions // برای تغییر دادهها از متدها استفاده میکنیم methods: { increment () { this.count++ } } })
یک برنامه ساده با استفاده از Vuex:
یک پروژه Vuejs را ایجاد کنید و مطابق تصویر زیر، گزینه دوم را انتخاب و Enter را فشار دهید:
سپس گزینه Vuex را طبق تصویر زیر با دکمهی space انتخاب کنید و برای مابقی گزینههای بعدی با زدن Enter، پیش فرضها را بپذیرید تا پروژه ساخته شود:
دو کامپوننت را به برنامه اضافه میکنیم.
کامپوننت اول با نام increase-counter-component.vue
<template> <div> <!-- نمایش شمارشگر --> <h1>{{count}}</h1> <!-- افزودن یک واحد به شمارشگر --> <button @click="add">Add 1</button> <!-- افزودن مقداری دلخواه به شمارشگر --> <button @click="add2">Add 2</button> </div> </template> <script> // یا همان منبع ذخیره دادهها store کردن import import store from "../store"; export default { // You can consider computed properties another view into your data. // https://css-tricks.com/methods-computed-and-watchers-in-vue-js/ computed: { count: () => store.state.count }, // به دو طریق فراخوانی شده add تابع methods: { // بدون پارامتر add: () => store.commit("add"), // با پارامتر // برای مقدار مورد نظر استفاده کنیم input میتوانیم بجای مقدار ثابت از یک add2: () => store.commit("add", 2) } }; </script>
کامپوننت دوم با نام decrease-counter-component.vue
<template> <div> <h1>{{count}}</h1> <button @click="subtract">Subtract 1</button> <button @click="subtract(3)">Subtract 3</button> </div> </template> <script> import store from "../store"; export default { computed: { count: () => store.state.count }, methods: { subtract: payload => store.commit("subtract", +payload) } }; </script>
<template> <div id="app"> <img alt="Vue logo" src="./assets/logo.png" /> <counter-plus></counter-plus> <hr /> <hr /> <counter-minus></counter-minus> </div> </template> <script> import counterPlus from "./components/increase-counter-component"; import counterMinus from "./components/decrease-counter-component"; export default { name: "app", components: { "counter-plus": counterPlus, "counter-minus": counterMinus } }; </script>
import Vue from 'vue' import Vuex from 'vuex' Vue.use(Vuex) export default new Vuex.Store({ // دادههای به اشتراک گذاشته شده state: { count: 0 }, // تعریف متدها mutations: { add(state, payload) { // If we get a payload, add it to count // Else, just add one to count payload ? (state.count += payload) : state.count++; }, subtract(state, payload) { payload ? (state.count -= payload) : state.count--; } } });
npm run serve
npm install
npm run serve
"baseUrl": "src", "paths": { "@app/*": [ "app/*" ], "@app/core/*": [ "app/core/*" ], "@app/shared/*": [ "app/shared/*" ], "@env/*": [ "environments/*" ], "my-lib": [ "../dist/my-lib" ], "my-lib/*": [ "../dist/my-lib/*" ] }
در زامارین 2 نوع layout داریم
FindViewbyid در پارامتر ورودی خود از طریق Resource.id، نام کنترل را دریافت نموده و بصورت Object باز میگرداند که بایستی نتیجه خروجی را به کلاس همان کنترل Cast نماییم:
Button btn = FindViewById<Button>(Resource.Id.button1);
FindViewById<EditText>(Resource.Id.txtname).Text = "";
هر layout یک اکتیویتی مربوط به خودش را دارد. اگر بخواهیم بین فرمهای مختلف حرکت کنیم، به ازای هر فرم، یک Activity کنترل کننده همان فرم را اضافه میکنیم. در یک Activity با ارسال سیگنالی به نام Intent که پارامتر اول آن، Activity مبدا یا This و پارامتر دوم آن، Activity مقصد میباشد. سپس به سیستم عامل اطلاع میدهیم که میخواهیم این سیگنال را ارسال کنیم و ارسال آن با StartActivity میباشد:
Intent _intent = new Intent(this, typeof(Activity2)); StartActivity(_intent);
ارسال پارامتر
جهت ارسال دادههای معمولی bool,double,string,float,long,... و آرایه ای از آن، از دستور PutExtra استفاده میشود:
Intent _intent = new Intent(this, typeof(Activity2)); string Test="Vlaueone"; _intent.PutExtra("mainactivity", Test); StartActivity(_intent);
گرفتن پارامتر
در Activity مقصد، اطلاعات مربوط به سیگنال ارسال شده، در مقادیر Global intent ذخیره میشود و بر اساس نوع داده ارسال شده، تابع GetExtra را مینویسیم:
string Getintent = Intent.GetStringExtra("mainactivity");
ارسال object از کلاسها بین Activityها
در زامارین، object کلاسها را به یک string استاندارد بصورت json تبدیل میکنیم و به این عملیات Serialization گفته میشود. این کار نیز توسط کتابخانههای مختلفی انجام میشود مانند NewtonSoft. سپس رشته json ایجاد شده را با تابع PutExtra، به همراه سیگنال Intent، به Activity دوم پاس میدهیم:
List<Product> products; products = new List<Product>(); Product p = new Product { name = FindViewById<EditText>(Resource.Id.mainedittextname).Text, price = Convert.ToInt32(FindViewById<EditText>(Resource.Id.mainedittextprice).Text) }; products.Add(p); Intent _intent = new Intent(this, typeof(Activity2)); _intent.PutExtra("products", JsonConvert.SerializeObject(products)); StartActivity(_intent);
var p = JsonConvert.DeserializeObject<List<Product>>(Intent.GetStringExtra("products")); foreach (var item in p) { Toast.MakeText(this, $" {item.name} , {item.price}", ToastLength.Long).Show(); };
در ادامه کلاسهای مورد نظر را جهت تعریف در دایرکتوری Model ایجاد میکنیم. مثل کلاس Product که بصورت Public نیز میباشد. از منوی Tools -> Nuget Package Management -> Manage nuget Package for Solution را انتخاب و سپس NewtonSoft را اضافه میکنیم.
AlertDialog زیر کلاس Dialog است که میتواند یک، دو و یا سه دکمه را نمایش دهد. اگر فقط میخواهید یک رشته را در این کادر محاوره ای نمایش دهید، از روش SetMessage استفاده کنید. قطعه کد زیر میتواند برای ایجاد یک AlertDialog ساده با دو دکمه حذف و لغو استفاده شود:
//set alert for executing the task AlertDialog.Builder alert = new AlertDialog.Builder(this); alert.SetTitle("Confirm delete"); alert.SetMessage("Lorem ipsum dolor sit amet, consectetuer adipiscing elit."); alert.SetPositiveButton("Delete", (senderAlert, args) => { Toast.MakeText(this, "Deleted!", ToastLength.Short).Show(); }); alert.SetNegativeButton("Cancel", (senderAlert, args) => { Toast.MakeText(this, "Cancelled!", ToastLength.Short).Show(); }); Dialog dialog = alert.Create(); dialog.Show();
Fragment
public class DialogFragmentActivity : DialogFragment { public override View OnCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { var dlg = inflater.Inflate(Resource.Layout.layoutDialog, container, false); return dlg; } }
DialogFragmentActivity dlg = new DialogFragmentActivity (); dlg.Show(this.FragmentManager, "Fragment");
public override void OnStart() { base.OnStart(); Dialog dialog = Dialog; if (dialog != null) { dialog.Window.SetLayout(ViewGroup.LayoutParams.MatchParent, ViewGroup.LayoutParams.WrapContent); dialog.Window.SetBackgroundDrawable(new ColorDrawable(Color.Transparent)); } }
public override Dialog OnCreateDialog(Bundle savedInstanceState) { Dialog NotTitle = base.OnCreateDialog(savedInstanceState); NotTitle.Window.RequestFeature(WindowFeatures.NoTitle); return NotTitle; }
ng build --prod
// environment.ts environment variables export const environment = { production: false, APIEndpoint: 'https://dev.endpoint.com' }; // environment.prod.ts environment variables export const environment = { production: true, APIEndpoint: 'https://prod.endpoint.com' };
import { environment } from './../environments/environment';
const APIEndpoint = environment.APIEndpoint;
// environment.staging.ts environment variables export const environment = { production: true APIEndpoint: "https://staging.endpoint.com" }; // environment.beta.ts environment variables export const environment = { production: true, APIEndpoint: "https://beta.endpoint.com" };
projects -> yourappname -> architect -> build -> configurations
"configurations": { "production": { "fileReplacements": [ { "replace": "src/environments/environment.ts", "with": "src/environments/environment.prod.ts" } ], "optimization": true, "outputHashing": "all", "sourceMap": false, "extractCss": true, "namedChunks": false, "aot": true, "extractLicenses": true, "vendorChunk": false, "buildOptimizer": true, "serviceWorker": true } }
"with":"src/environments/environment.prod.ts"
"with":"src/environments/environment.staging.ts"
"configurations": { "production": { // ... }, "staging": { "fileReplacements": [ { "replace": "src/environments/environment.ts", "with": "src/environments/environment.staging.ts" }], "optimization": true, "outputHashing": "all", "sourceMap": true, "extractCss": false, "namedChunks": false, "aot": false, "extractLicenses": true, "vendorChunk": false, "buildOptimizer": true, "serviceWorker": true } }
//for staging environment ng build --configuration=staging //for beta environment ng build --configuration=beta
//for production environment ng build --prod //for dev environment ng build