שיעור 9 ב- ionic, שליטה בעיצוב הדף

כדי לשלוט בעיצוב, ionic משתמשת בקובץ scss, עבור כל עמוד בנפרד.

כאשר, בנוהל הרגיל של scss, אפשר לשרשר הגדרות בהיררכיה מסויימת.

איך זה מתקמפל ?

בזמן שנריץ, אז ionic תאחד את כל קבצי ה-scss, אל קובץ css אחד גדול

  • מה נגזר מכך ?
    • שאם נשים הגדרת css מחוץ לסוגרים שקשורים לעמוד , אז הם יהיו למעשה הגדרת css כוללת, שתוחל על כלל העמודים.

המחשה

התוצאה של קטעי הקוד הבאים, תהיה תגית p בצבע רקע אדום , רק בתוך עמוד ה-users.

 --- In the HTML file -----
 
 <p>Hi Man</p>
 
 
 --- In the scss File ----
 page-users {
 p {
 background-color: red;
 }
}

הגדרות כלליות של תבנית העיצוב ב-ionic

תחת תיקית theme, נמצא קובץ variables , ובו יש הגדרות כלליות של הצבעים, אפשר לשנות ולראות

$colors: (
 primary: #848484,
 secondary: #32db64,
 danger: #f53d3d,
 light: #f4f4f4,
 dark: #222
);

 

שיעור 13 באנגולר (angular) – מספר שיטות ל- Data Binding

באנגולר יש מספר שיטות לבצע Data Binding, כלומר לקשור בין ערך של משתנה בקלאס ובין משהו שמוצג על המסך.

נראה 3 שיטות, כולן משיגות את אותה תוצאה בסופו של דבר :

import { Component, OnInit } from '@angular/core';

@Component({
 selector: 'app-data-binding2',
 template: `
 <img src="{{ imageUrl }}">
 <img [src]="imageUrl" >
 <img bind-src="imageUrl">
 
 
 `
})
export class DataBinding2Component implements OnInit {

 imageUrl:string = 'http://lorempixel.com/400/200';

 constructor() { }

 ngOnInit() {
 }

}

איך לקשור את תוכן התגית ב-HTML, באמצעות אנגולר

ישנה אפשרות נוספת להחליט על התוכן, באמצעות המאפיין [textContent]

זה נראה כך, והתוצאה היא שהטקסט שמוצג בתוך ה-span, הוא תוכן המשתנה.

<h4>Image URL : <span [textContent]="imageUrl"></span></h4>

איך לבצע הדלקה\כיבוי של פרמטרים בוליאנים באמצעו אנגולר

לעיתים יש מאפיינים בוליאנים של תגיות, כמו

  • "האם התגית צריכה להיות מוצגת או מוסתרת?"
  • האם הכפתור צריך להיות מאופשר או חסום ללחיצה ?

לצורך כך , נגדיר משתנה בוליאני , ונשייך אותו למאפיין המתאים :

import { Component, OnInit } from '@angular/core';

@Component({
 selector: 'app-data-binding2',
 template: `
 
 <p [hidden]="!postChanged">Remmber to Save this post.</p>
 <button [disabled]="!postChanged">Save Post</button>

 `
})
export class DataBinding2Component implements OnInit {

 postChanged:boolean = false;

 constructor() { }

 ngOnInit() {
 }

}

שיעור 8 ב- ionic – מחזור חיים של דף

לדף ב-ionic, יש אירועים שהוא מגיב אליהם.

האירועים האלו הם בנוסף לאירועים הרגילים שעוברים על כל angular component.

ישנם מספר אירועים אפשריים

רשימה של האירועים קיימת בדוקומנטציה ( תחת הכותרת lifecycle events).

  • אירועים "רגילים" מחזירים כלום (כלומר void), ופשוט מתרחשים בזמן שצריך.
  • אירועים שמחזירים תשובה בוליאנית, או promise בוליאני, ובהם אפשר להגיב להתרחשות \ אי-התרחשות של האירוע.

דוגמא למימוש אירוע רגיל

למשל סוג האירוע שמתרחש כאשר הדף נטען לראשונה למערך.

כדי לממש אותו, פשוט נכתוב בקובץ ה-ts פונקציה שנקראת בשם של האירוע – והוא יקרה.

ionViewDidLoad() {

console.log('ionViewDidLoad UsersPage');

}

 

כעת נראה דוגמא יותר מורכבת, לאירוע שמחזיר הבטחה, יש רק 2 אירועים כאלו, והם חייבים להיות כתובים לפני האירועים האחרים.

דוגמא למימוש אירוע עם תשובה בוליאנית, ושליטה בהרשאת הכניסה לעמוד.

בדוגמא הבאה, קיים כפתור בדף home שמפנה לדף users.

בדף users, מימשתי אירוע של  ionViewCanEnter, כאשר ה-תשובה הבוליאנית , חוזרת  אל הפונקציה שטענה את הדף אל תוך המערך – כלומר התשובה מוחזרת לפונקציה בדף  home.

ושם, בפונקציה המקורית – אני מגיב לתשובה שהוחזרה.

------- On home.ts file ---
 onGoToNewPage() {
 this.navCtrl.push(UsersPage)
 .then ((msg) => msg ? console.log("can access") : console.log("not access"));
 }
 
------ On users.ts file ---
ionViewCanEnter(): boolean|Promise<boolean>{
 console.log('ionViewCanEnter');
 const rnd = Math.random();
 console.log(rnd);
 return rnd>0.5;
 }

 

שיעור 12 באנגולר (angular) – תנאים ngIf

בפוסט הזה, נראה כיצד לממש תנאים באנגולר.

תנאים באנגולר עם ngIf*

הצורה הפשוטה ביותר היא עם directive שנקרא ngIf*.

כאשר בתוך המרכאות נותנים לו ביטוי בוליאני, ובהתאם, הוא "משליך" על התגית בה הוא נמצא.

לדוגמא הקוד הבא – יציג\יסתיר את השם לפי ערך המשתנה הבוליאני.

import { Component, OnInit } from '@angular/core';

@Component({
 selector: 'app-ngif2',
 template:`
 <p>My Name is : <span *ngIf="showName">{{name}}</span></p>
 `
})
export class Ngif2Component implements OnInit {

 name:string = "Eyal";
 showName:boolean = true;

 constructor() { }

 ngOnInit() {
 }

}

נניח ונרצה לגרום לתנאי לעבוד בצורה הפוכה, כלומר, כל פעם שהשם לא מוצג, אז מוצג משהו אחר.

דרך פשוטה לעשות זאת, היא עם סימן קריאה לפני הביטוי הבוליאני (כלומר, כל עוד הביטוי לא מתקיים, אז התנאי הבוליאני כן מתקיים).

דוגמא :

import { Component, OnInit } from '@angular/core';

@Component({
 selector: 'app-ngif2',
 template:`
 <p>My Name is : 
 <span *ngIf="showName">{{name}}</span>
 <span *ngIf="!showName">{{'KOKO'}}</span>
 
 
 </p>
 `
})
export class Ngif2Component implements OnInit {

 name:string = "Eyal";
 showName:boolean = false;

 constructor() { }

 ngOnInit() {
 }

}

אבל, ברור שצריך אפשרות נורמלית ל-else. וזו הדוגמא הבאה.

תנאי ngIf באנגולר עם else + היכרות עם ngTemplate

בקטע קוד הבא, אנחנו אומרים למעשה שאם התנאי לא מתקיים, אז …להציג את מה שנקרא bubu.

ומה שנקרא bubu , הוא תבנית, שאנחנו מגדירים מייד לאחר מכן.

אפשר להגדיר כמה תבניות שרוצים, כל עוד נותנים להם שם יחודי באמצעות סולמית בהתחלה.

<h1>ngIf with Else And Template</h1>
 <p>My Name is :
 <span *ngIf="showName; else noname">{{name}}</span>
 <ng-template #noname >KOKO</ng-template>
 </p>

תנאי  ב-JS – בצורה מקוצרת

וכמו בכל השפות, יש גם צורה מקוצרת. אז גם באנגולר...למעשה יותר נכון, גם ב-JS , יש צורה מקוצרת, נציין אותה כאן בכל מקרה.

 <p>Hello {{ showName ? name : 'koko' }}</p>

תנאים מרובים באנגולר עם ngSwitch*

ויש גם צורה להגיב לתנאי עם אפשרויות מרובות.

 ----- In the class ----
 personType:number = 2;

 ----- In the HTML template -----
 <div [ngSwitch]="personType">
 <span *ngSwitchCase="'1'" >Nice person</span>
 <span *ngSwitchCase="'2'"> Evil Person</span>
 <span *ngSwitchDefault> Just normal </span>
 </div>

 

שיעור 7 ב- ionic – קיצורים לניווט

לניווט במקרה שאין צורך בפרמטרים, יש Directives יעודיים של ionic .

נראה אותם בפעולה.

דוגמא 1 – קיצור ב-ionic לניווט לדף ללא העברת פרמטרים.

נעשה 2 פעולות

  • בקובץ ה-ts , נגדיר משתנה שמכיל את הדף שאליו אנחנו רוצים לנווט
    • כמובן צריך לייבא את הדף המתאים.
  • בקובץ ה-html, נכניס כפתור עם הפקודה המקוצרת navPush

התוצאה תהיה כפתור ניווט לדף הרצוי, בלי צורך לממש פונקציה יעודית, ובלי צורך לייבא את navController וכו'.

להלן דוגמת קוד :

------ In TypeScript Component File ------
import { AboutPage } from './../about/about';

...
...

export class HomePage {

 abPage = AboutPage;
 
 ------- In HTML file ------

 <button ion-button [navPush]="abPage">Go To About Page</button>

דוגמא 2 – קיצור לניווט לאחור

אם נרצה כפתור שרק חוזר לאחור, נשתמש ב-directive שנקרא navPop.

להלן דוגמת קוד :

<buttonion-buttonnavPop>Go Back</button>

שיעור 11 באנגולר (angular) – לולאות עם ngFor Directive

בפוסט הזה נראה כיצד לרוץ בלולאה באנגולר.

דוגמא 1 – לולאה פשוטה על מערך באנגולר , באמצעות ngFor*

לצורך בסיס לדוגמא הראשונה, נראה קודם כל איך אנגולר מציג לנו מערך רגיל, ללא לולאה.

אם נפעיל את הקוד הבא, אנגולר יציג לנו את תוכן המערך, מופרד בפסיקים.

import { Component, OnInit } from '@angular/core';

@Component({
 selector: 'app-ngfor3',
 template: ` 
 The products are : {{ products }}
 `
})
export class Ngfor3Component implements OnInit {

 products:string[] = ['bread','milk','rice','water'];

 constructor() { }

 ngOnInit() {
 }

}

עכשיו, נניח ונרצה לרוץ בלולאה על המערך ולהציג אותו בנקודות.

לצורך כך נשתמש ב-ngFor.

הוא מתחיל בסימן כוכבית *, ולאחריו בתוך מרכאות, אנחנו כותבים בדומה לשפות אחרות, מהו המשתנה שמקבל את הסמן בלולאה, ומהו המערך שעליו רצים.

התוצאה של זה תהיה תצוגה בנקודות של הרשימה .

להלן רק קטע הקוד שהשתנה :

 template: ` 
 <ul>
 <li *ngFor="let product of products">
 {{product}}
 </li>
 </ul>
 
 `

דוגמא 2 – לולאה עם 2 סמנים בו זמנית באנגולר, באמצעות ngFor*

אם נוסיף עוד סמן ללולאה, אפשר יהיה להוסיף את המספרים שלהם על יד כל נקודה. (הוספתי 1 כדי להתחיל מ-1 ולא מאפס).

 template: ` 
 <ul>
 <li *ngFor="let product of products;let i = index">
 {{ i+1 }} -> {{product}}
 </li>
 </ul>
 `

דוגמא 3 – לולאה על מערך של אובייקטים באנגולר, באמצעות ngFor*

בדוגמא הבאה, יש לנו מערך של אובייקטים, ואנחנו מציגים מאפיינים של האובייקט.

import { Component, OnInit } from '@angular/core';

@Component({
 selector: 'app-ngfor3',
 template: ` 
 <ul>
 <li *ngFor="let product of products;let i = index">
 {{ i+1 }} -> {{product}}
 </li>
 </ul>

 <ul>
 <li *ngFor="let habbit of habbits">
 Habbit Name: {{habbit.Title}} | is it risky: {{ habbit.isRisky }}
 </li>
 </ul>
 `
})
export class Ngfor3Component implements OnInit {

 products:string[] = ['bread','milk','rice','water'];

 habbits = [
 {
 'Title': 'surf',
 'isRisky': 'Yes'
 },
 {
 'Title': 'smoke',
 'isRisky': 'Yes'
 }
 ];

 constructor() { }

 ngOnInit() {
 }

}

הערה לסיום – שינוי תוכן המערך לפני התצוגה על המסך

כיוון שהמערכים נוצרים כשנוצר המופע של המחלקה, אז אפשר לשנות אותם בתוך הקונסטרטור, והשינוי כמובן ישתקף במה שמוצג על המסך.

אם לדוגמא נשנה את רמת הסיכון של אחד התחביבים ברשימה, כמובן שזה ישתקף ברשימה על המסך.

 constructor() {
 this.habbits[1].isRisky = "No";
 }

 

 

שיעור 10 באנגולר (angular) – שימוש בקובץ תבנית חיצוני (html) ובקובץ עיצוב חיצוני (css).

בפוסט הזה נראה דוגמא פשוטה לשימוש בקובץ html+css חיצוניים (שזוהי ברירת המחדל שמיוצרת על ידי כלי angular cli).

קובץ ה-ts שלנו, מכיל את הגדרת ה-Component@ , שמכילה הפניות ל-2 קבצים חיצוניים.

להלן 3 הקבצים :

----------- TypeScript File ---------------------

import { Component, OnInit } from '@angular/core';

@Component({
 selector: 'app-outside-files',
 templateUrl: './outside-files.component.html',
 styleUrls: ['./outside-files.component.css']
})
export class OutsideFilesComponent implements OnInit {

 constructor() { }

 ngOnInit() {
 }

}
--------- HTML file ---------
<p class="sss">
 outside-files works!
</p>
--------- CSS file ----------
.sss {
 background-color: yellow;
 color: red;
}

שיעור 9 באנגולר (angular) -אובייקטים ואינטרפייס עם TypeScript.

הפוסט הזה  מדגים את האפשרות ליצור אובייקטים עם TypeScript.

דוגמא 1 – משתנה מסוג אובייקט

כך נגדיר משתנה מסוג אובייקט

Person:{
 id:number,
 name:string,
 email:string
}

וכך נשים בו ערכים

this.Person = {
 id:887,
 name: 'Bubu',
 email: 'bubu@jjj.com'
 }

 

דוגמא 2 – שימוש ב-interface + מערך של אובייקטים.

את אותה הגדרה בדיוק, אפשר להפריד לקובץ נפרד, ולהגדיר אובייקט שמממש interface.

בקובץ נפרד נגדיר כך :

export interface Person {
 id:number,
 name:string,
 email:string
}


כעת בקובץ TypeScript שמכיל את המודל של ה-component :

  • נייבא את ה-interface
  • ולאחר מכן, נוכל להשתמש באינטרפייס שבנינו

בקומפוננט הבא אפשר לראות גם משתנה בודד שמוגדר ע"פ האינטרפייס, וגם מערך .

import { Component } from '@angular/core';
import { Customer } from './Customer'

@Component({
 selector: 'sandbox3',
 template: `
 <p style="color:red;">Hello from SandBox3</p>
 `
})

export class Sandbox3Component{
 customer:Customer;
 customers:Customer[];

 constructor() {
 this.customer = {
 id: 1,
 name: 'Zuyyyyy',
 email: 'bubu@momo.com'
 }

 this.customers = [
 {
 id: 1,
 name: 'Zuyyyyy',
 email: 'bubu@momo.com'
 },
 {
 id: 2,
 name: 'bbdbdbdb',
 email: 'bfbfbf@momo.com'
 },
 {
 id: 3,
 name: 'ffffffd',
 email: 'rrd@momo.com'
 }
 ]
 }
}

וולידציה פשוטה ב-ASP.NET Core Web Api

איך עושים וולידציה ב-ASP.NET Core WebApi ?

  • עבור כל אלמנט במודל שנרצה לבדוק – נוסיף Data Annonations על תוכן הוולידציה.
  • בפונקציה עצמה, נפעיל מתודה שבודקת האם המודל עבר וולידציה.

 

דוגמא למודלים עם ולידציה :

public class JustTry {
 
 [Range(15,34)]
 public int Id { get; set; }

 [MaxLength(30)]
 public string Koko { get; set; }


}

------------- OTHER MODEL WITH DATA ANNONATIONS --------
[Required]
 [StringLength(100)]
 public string Name { get; set; }

 [Required]
 [EmailAddress]
 public string Email { get; set; }

 [Required]
 [Phone]
 public string Phone { get; set; }

 [Required]
 [Url]
 public string Site { get; set; }

 [Range(0,130)]
 public int? Age { get; set; }

 [Required]
 [StringLength(500)]
 public string Message { get; set; }

מימוש פונקציה עם ולידציה :

[HttpPost]
 public IActionResult Post([FromBody]JustTry jj)
 {
 if (!ModelState.IsValid)
 {
 return BadRequest();
 }

 
 ... 
 ... Your Code here to save etc.etc. ...
 ...
 ...

 return Created("Get",jj);
 }

דוקומנטציה – נמצאת בקישור הזה – https://docs.microsoft.com/en-us/aspnet/core/mvc/models/validation .

והמחשה לשילוב עם אנגולר בקישור הזה – http://www.carlrippon.com/?p=720.

 

שיעור 6 ב- ionic – מימוש כפתור חזרה לאחור

בפוסט זה נדגים יצירה של כפתור "חזור אחורה" (שאינו חלק מהתפריט העליון).

כפי שהסברתי באחד הפוסטים הקודמים, הניווט של ionic הוא למעשה מערך. עד כה בכפתורים שיצרנו בפוסט הקודם – רק הוספנו פריט למערך. כעת נציג דוגמא בה אנחנו מסירים פריט מהמערך – ולמעשה באותו רגע חוזרים לאחור.

  • הוספתי הזרקה של navController, וכמובן גם import מתאים.
  • מימשתי כפתור בקובץ ה-HTML.
  • מימשתי פונקציה עבור הכפתור בקובץ ה-Type Script.
קובץ ה-html
--------------------
<ion-header>
<ion-navbar>
<ion-title>MyTitle</ion-title>
</ion-navbar>
</ion-header>
<ion-content>
<p>שמי הוא {{ name }}</p>
<buttonion-button (click)="onGoBack()">Go Back</button>
</ion-content>


--------------
קובץ ה-ts
-------------
import { Component, OnInit } from '@angular/core';

import { NavParams, NavController } from 'ionic-angular';

@Component({

selector:'page-user',

templateUrl:'user.html'

})

export class UserPage implements OnInit {

name:string;

constructor(privatenavParams:NavParams,privatenavCtrl:NavController) {

}

ngOnInit() {

this.name=this.navParams.get("userName");

}

onGoBack() {

this.navCtrl.pop();

}

}

חזרה לעמוד הראשי ב- ionic

לאובייקט navController יש מתודה נחמדה שנקראת popToRoot והיא מסירה את כל העמודים, עד לעמוד הראשי – שימושי ביותר.