סלקטורים ב-CSS ( סיכום )

לפעמים אני חוזר על חומרים בסיסיים לעצמי. החלטתי לחזור קצת על CSS Selectors, כי ביום-יום אני פחות מתעסק עם זה (כל החיתוכים ל-html נשלחים לחו"ל).

  • ב-CSS יש מספר אפשרויות לבחור את האלמנטים בדף.
  • האפשרויות האלו נקראות Selectors.
  • והן משמשות אותנו גם ב-JS כדי לבחור אלמנטים בדף.

סיכום מקוצר של Css Selectors

  • id ——– #bubu
  • class ———.myClass
  • Descendant ——- p a li
  • state —— input:foucs
  • excat hirarcy – li:nth-child(2n

קדימות ב-CSS

לפי הסדר הבא : inline style > id > classes > elements

סוגי Css Selectors

  • לפי id של האלמנט – מתחיל בסימן סולמית

המחשה :

#myId {
bla...
bla...
}
  • לפי class  – מתחיל בסימן נקודה

המחשה :

.myClass {
bla...
bla...

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

המחשה  –  רק תגיות a עם הקלאס bubu  שנמצאות בתוך פיסקה (p) – רק הן יבחרו.

p a .bubu {
bla
bla...

  • לפי מצב האלמנט (hover… ) – מסומן בסימן נקודתיים :

המחשה :

input:focus { 
dsfsd
sdf

  • לפי רמת היררכיה מדוייקת בעץ – משתמשים במילים קבועות כמו first-child , או לחלופין בפקודת ה-CSS nth-child עם מספר הרמה בהיררכיה בתוך סוגרים

המחשה :

.myClass:nth-child(2n) {
bla..
bla..
}

li:first-child {
bla..
bla...
}

 

כללי קדימויות ב-CSS

  • הקדימות ב-CSS היא לפי הדירוג הבא :
    • תגית style בתוך ה-HTML
    • אחריה CSS שעוסקים ב- #id
    • אחריה CSS עבור קלאסים
    • ואחריה CSS עבור אלמנטים רגילים.

גיבוי , ושיחזור מגיבוי של MariaDb / MySql

בפוסט הזה, אציג בקצרה גיבוי ושיחזור של DB של mysql .

 

גיבוי mysql \ MariaDb

יש כלי cli שנקרא mysqldump ,

השימוש בו פשוט מאוד,

mysqldump --user MY_USER_NAME MY_DATABASE_NAME > MY_BACKUP_FILE_NAME.sql
  •  שימו לב שבאפשרות הבסיסית, אין את משפט ה- Create Database
  • בנוסף, אם אתם משתמשים בו על Windows, אז כדאי לשים לב לגודל האותיות, כיוון שהתקנת ברירת המחדל במערכות Windows, היא כאשר כל האותיות בשמות הטבלאות \ DB – הם קטנות, ובלינוקס…זה מהותי.

שיחזור מגיבוי MySql \ MariaDB

  • לכלי ה-cli הרגיל של mysql\mariadb , יש אפשרות  לקבל קבצים בתור קלט (כמו כל תוכנת cli נורמלית)
  • רק …צריך לודא שהקובץ מכיל את ה-use המתאים לדאטאבייס שאתם רוצים.
  • ובמידה ויוצרים DB , אז את משפט ה-Create  המתאים.

השימוש :

mysql -u MY_USER_NAME < MY_IMPORTED_FILE_NAME.sql

 

הערה כללית :

  • כמובן במידה והיוזר שאיתו אתם ניגשים דורש סיסמא, אזי הוסיפו את האפשרות הבאה
-pPASSWORD

שימו לב שהסיסמא "דבוקה" לתגית ה-p.

בהצלחה

יכולות מספור ומעבר עמודים של wkhtmltopdf

יצירת PDF באתר אינטרנט

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

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

אני כבר כמה שנים משתמש בכלי צד שרת שנקרא wkhtmltopdf.

ההתקנה על windows קלה ביותר.

ההתקנה על linux , עם עברית – עשויה להיות מורכבת, ולא פשוטה כלל.

אחרי שהכלי מותקן על השרת ועובד, השימוש בו מאוד פשוט, זהו למעשה דפדפן שרת פקודה, שמאפשר להדפיס כל עמוד html, לקובץ PDF, עם יכולות עימוד טובות.

כמובן , שצריך לבצע התאמות CSS וכו',

בפוסט הזה אראה 2 יכולות שלו בנוגע למעבר עמוד, ובנוגע למיספור:

מעברי עמוד ב- wkhtmltopdf

  • יש אנשים שפשוט ידאגו שכל העמודים יהיו בגודל של A4, וגם זו שיטה.
  • אני פחות אוהב, ולכן אני מגדיר 3 קלאסים של CSS ומשתמש בהם לפי הצורך.
  • אין צורך לשים את זה ב-media של print, כי זה פשוט לא יעבוד.
.keep-together {

    page-break-inside: avoid;

}

.break-before {

    page-break-before: always;

}

.break-after {

    page-break-after: always;

}

מספרי עמודים ב-wkhtmltopdf

  • אני מדגים את מספרי העמודים בהנחה שיש לכם עמוד \ route נפרד עבור ה- footer
  • אבל…זה אפשרי כמובן לשלב בעמוד של ה-content העיקרי.
  • הרעיון פשוט – מגדירים פונקצית JS שמעבירה את העמודים
  • בתגית ה- body  – נפעיל אותה
  • ואז במקום שנרצה נשים את הערכים הרלוונטים עבור עמוד…מתוך….
<script>
  function subst() {
      var vars = {};
      var query_strings_from_url = document.location.search.substring(1).split('&');
      for (var query_string in query_strings_from_url) {
          if (query_strings_from_url.hasOwnProperty(query_string)) {
              var temp_var = query_strings_from_url[query_string].split('=', 2);
              vars[temp_var[0]] = decodeURI(temp_var[1]);
          }
      }
      var css_selector_classes = ['page', 'frompage', 'topage', 'webpage', 'section', 'subsection', 'date', 'isodate', 'time', 'title', 'doctitle', 'sitepage', 'sitepages'];
      for (var css_class in css_selector_classes) {
          if (css_selector_classes.hasOwnProperty(css_class)) {
              var element = document.getElementsByClassName(css_selector_classes[css_class]);
              for (var j = 0; j < element.length; ++j) {
                  element[j].textContent = vars[css_selector_classes[css_class]];
              }
          }
      }
  }
</script>
<body  onload="subst()">

 

עמוד <span class="page"></span> מתוך <span class="topage"></span>

שיעור 23 באנגולר ( angular ) – העברת מידע לתוך קומפוננטה

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

עושים זאת באמצעות הפקודה Input@

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

דוגמא – יש פה 2 קבצים, בקובץ העליון, אני מעביר משתנה בשם question

ובקובץ השני, הפנימי יותר, אני מקבל אותו עם Input@.

------------- First component ----------------
<app-question *ngFor="let question of questions" [question]="question" ></app-question>


-------------- Seconed Component TS file-------------
import { Question } from './../../models/Question';
import { Component, OnInit,Input } from '@angular/core';


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

@Input('question') question:Question;

constructor() { }

ngOnInit() {
 }

}

 

שיעור 22 באנגולר ( angular ) – שימוש ב- router

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

כדי להשתמש בו נבצע את השלבים הבאים :

  • נוודא שישנה תגית base
  • נייבא את ה- router ב- app.module.ts
  • נגדיר מערך של ניתובים
  • נוסיף למערך imports, את המערך של הניתובים, דרך המתודה שנקראת forRoot()
  • בתוך app.component.html נוסיף תגית router-outlet
  • ונקשר בתוך הקומפוננוטות במקומות הנחוצים – באמצעות הוספת המאפיין routerLink לתגית ה- a
--- app.module.ts --------
...
...
import { RouterModule,Routes } from '@angular/router';
...
...
import { Home3Component } from './components/home3/home3.component';

const appRoutes: Routes = [
 { path: '', component: Home3Component},
 { path : 'about', component: AboutComponent},
 { path: 'user/:id', component: UserDetailsComponent}
];
...
...
...
imports: [
 BrowserModule,
 FormsModule,
 HttpModule,
 RouterModule.forRoot(appRoutes)
 ],
 

--- app.component.html -------
...
...

<router-outlet></router-outlet>
...
...
---- navbar.component.html ------
 <li class="nav-item active">
 <a class="nav-link" href="#" routerLink="/" >Home <span class="sr-only">(current)</span></a>
 </li>
 <li class="nav-item">
 <a class="nav-link" href="#" routerLink="/about">Link</a>
 </li>

ניתובים (כתובת URL ) עם פרמטר

  • ניתן להוסיף ניתובים עם פרמטרים ב-syntax הבא:    blabla/:myParam
  • כדי לקבל את הכתובות , נייבא אל תוך הקומפוננט את
    Router,ActivatedRoute,Params
  • ובנוסף נזריק ( DI ) בקונסטרקטור את Router,ActivatedRoute
  • כדי שנוכל לקבל את הפרמטר מה-URL, צריכים לרשום = subscribe  את הפרמטר בתוך "צופה"  = observable.

 

---- in app.module.ts routes array ----

const appRoutes: Routes = [
 { path: '', component: Home3Component},
 { path : 'about', component: AboutComponent},
 { path: 'user/:id', component: UserDetails3Component}
];

--- in the component -----
import { Component, OnInit } from '@angular/core';
import { Router,ActivatedRoute,Params } from '@angular/router';

@Component({
 selector: 'app-user-details-3',
 template: `
 <h1> This is User number {{id}}.</h1>
 `,
 
})
export class UserDetails3Component implements OnInit {

 id:number;

 constructor(
 private route:ActivatedRoute,
 private router:Router
 ) 
 {

 this.route.params.subscribe((params:Params) => {
 this.id = params.id;
 });
 }

 ngOnInit() {} 



}

שיעור 21 באנגולר (angular) – קריאות http

קריאת Get באנגולר, והבסיס לקריאות http

כדי להשתמש ברכיב http של אנגולר, צריך קודם כל לייבא אותו ולהגדיר אותו בקובץ app.module.ts

import { HttpModule } from '@angular/http';

...
...
imports: [
 BrowserModule,
 FormsModule,
 HttpModule,
 RouterModule.forRoot(appRoutes)
 ],

שלב נוסף – הוא בתוך ה- service, להזריק אותו אל הקונסטרטור (וכמובן לייבא אותו ).

(במידה וזה service חדש שעכשיו נוצר, אז כמובן לייבא אותו ב–app.module.ts, ולהכניס אותו למערך ה- providers ).

ואז ב- service, נשתמש במודול http כדי לבצע קריאה, ולמפות את התוצאות ל-json.

כדי למפות את התוצאות צריך לייבא חלק של rxjs, שנקרא map.

התוצאה הסופית נראית כך :

---- The Service file -----

import { Injectable } from '@angular/core';
import { Http } from '@angular/http';
import 'rxjs/add/operator/map';


@Injectable()
export class Get2Service {

 apiUrl:string = 'https://jsonplaceholder.typicode.com/users';

 constructor(public http:Http) { }

 getUsers(){
 return this.http.get(this.apiUrl)
 .map(response => response.json());
 }


}


----- The component file ----------

import { Component, OnInit } from '@angular/core';
import { Get2Service } from './../../services/get2.service';

@Component({
 selector: 'app-useget2',
 template: `
 
 <h1>list of users</h1>
 <div *ngFor="let user of users">
 <ul>
 <li>{{user.name}}</li>
 <li>{{user.email}}</li>
 <li>{{user.id}}</li>
 </ul>
 <hr>
 </div>
 
 `
})
export class Useget2Component implements OnInit {

 users:any[];

 constructor( public getService:Get2Service ) {

 this.getService.getUsers().subscribe(users => {
 //console.log(users);
 this.users = users;
 })

 }



 ngOnInit() {
 }

}

קריאת POST באנגולר

בדוגמא הבאה, לקחתי את הדוגמא הקודמת והוספתי לה

  • ב- service התווספה פונקציה שנקראת addUser ומבצעת קריאת POST.
  • ב-component התווסף טופס להוספת יוזרים, שממופה עם ngModel אל רשימת היוזרים, ואל משתנה חדש בשם יוזר ( אובייקט עם 3 מאפיינים).
  • לטופס יש פונקציה שמטפלת ב-submit שלו, שמבצעת גם קריאה ל-service.
---------- The Service File ------------------

import { Injectable } from '@angular/core';
import { Http } from '@angular/http';
import 'rxjs/add/operator/map';


@Injectable()
export class Get2Service {

 apiUrl:string = 'https://jsonplaceholder.typicode.com/users';

 constructor(public http:Http) { }

 getUsers(){
 return this.http.get(this.apiUrl)
 .map(response => response.json());
 }

 addUser(user) {
 return this.http.post(this.apiUrl,user).map(response => response.json());
 }


}
--------------- The component file -------------

import { Component, OnInit } from '@angular/core';
import { Get2Service } from './../../services/get2.service';

@Component({
 selector: 'app-useget2',
 template: `
 
 <h1>list of users</h1>
 <form (submit)="onSubmit()">
 <div class="form-group">
 <label>Name:</label>
 <input type="text" name="name" [(ngModel)]="user.name" class="form-control">
 </div>
 <div class="form-group">
 <label>Email:</label>
 <input type="text" name="email" [(ngModel)]="user.email" class="form-control">
 </div>
 <div class="form-group">
 <label>Phone:</label>
 <input type="text" name="phone" [(ngModel)]="user.phone" class="form-control">
 </div>
 <input type="submit" value="click to submit" class="btn btn-success">
 </form>
 <hr>
 <div *ngFor="let user of users">
 <ul>
 <li>{{user.name}}</li>
 <li>{{user.email}}</li>
 <li>{{user.id}}</li>
 </ul>
 <hr>
 </div>
 
 `
})
export class Useget2Component implements OnInit {

 users:any[];
 user = {name: '',
email:'',phone:''};

 constructor( public getService:Get2Service ) {

 this.getService.getUsers().subscribe(users => {
 //console.log(users);
 this.users = users;
 })

 }

 onSubmit(){
 this.getService.addUser(this.user).subscribe(user=> {
 console.log(user);
 this.users.unshift(user);
 });
 }

 ngOnInit() {
 }

}

קריאת Delete  + PUT  באנגולר

המשך הדוגמא שמובאת למעלה – הוספתי כעת גם קריאות put+delete שמוצמדות לכפתורים Edit/Delete.

(הכפתור edit , מעדכן את המודל, וכיוון שהטופס קשור ל- ngModel אז באופן אוטומטי, הטופס מכיל את תוכן המודל).

----- The Service File --------

import { Injectable } from '@angular/core';
import { Http } from '@angular/http';
import 'rxjs/add/operator/map';


@Injectable()
export class Get2Service {

 apiUrl:string = 'https://jsonplaceholder.typicode.com/users';

 constructor(public http:Http) { }

 getUsers(){
 return this.http.get(this.apiUrl)
 .map(response => response.json());
 }

 addUser(user) {
 return this.http.post(this.apiUrl,user).map(response => response.json());
 }

 deleteUser(id) {
 return this.http.delete(this.apiUrl + "/" + id).map(response => response.json());
 }

 updateUser(user) {
 return this.http.put(this.apiUrl + '/' + user.id,user).map(response => response.json());
 }

}


---- The Component file -----------
import { Component, OnInit } from '@angular/core';
import { Get2Service } from './../../services/get2.service';

@Component({
 selector: 'app-useget2',
 template: `
 
 <h1>list of users</h1>
 <form (submit)="onSubmit(isEdit)">
 <div class="form-group">
 <label>Name:</label>
 <input type="text" name="name" [(ngModel)]="user.name" class="form-control">
 </div>
 <div class="form-group">
 <label>Email:</label>
 <input type="text" name="email" [(ngModel)]="user.email" class="form-control">
 </div>
 <div class="form-group">
 <label>Phone:</label>
 <input type="text" name="phone" [(ngModel)]="user.phone" class="form-control">
 </div>
 <input type="submit" value="click to submit" class="btn btn-success">
 </form>
 <hr>
 <div *ngFor="let user of users">
 <ul>
 <li>{{user.name}}</li>
 <li>{{user.email}}</li>
 <li>{{user.id}}</li>
 </ul>
 <br>
 <button (click)="onDeleteClick(user.id)" class="button btn-danger btn-sm">Delete</button>
 <button (click)="onEditClick(user) " class="button btn-primary btn-sm">Edit</button>
 <hr>
 </div>
 
 `
})
export class Useget2Component implements OnInit {

 users:any[];
 user = {name: '',
email:'',phone:''};
 isEdit:boolean = false;

 constructor( public getService:Get2Service ) {

 this.getService.getUsers().subscribe(users => {
 //console.log(users);
 this.users = users;
 })

 }

 onSubmit(isEdit){
 if (isEdit) {
 this.getService.updateUser(this.user).subscribe(user=> {
 console.log(user);
 for(let i = 0; i< this.users.length ; i++ ){
 if (this.users[i].id == user.id) {
 this.users.splice(i,1);
 
 }
 }
 this.users.unshift(user);
 });
 } else {

 this.getService.addUser(this.user).subscribe(user=> {
 console.log(user);
 this.users.unshift(user);
 });
 }
 }

 ngOnInit() {
 }


 onDeleteClick(id) {
 console.log(id);
 this.getService.deleteUser(id).subscribe(response=> {
 console.log(response);
 for(let i = 0;i< this.users.length; i++) {
 if(this.users[i].id == id) {
 this.users.splice(i,1);
 }
 }
 });
 }

 onEditClick(user) {
 this.isEdit = true;
 this.user = user;
 }
}

 

שיעור 20 באנגולר ( angular) – שימוש ב – obseravables

מהו Observable ?

  • במקור זהו Design Pattern מקובל ( הסבר מוויקיפדיה  )  שיש לו מימושים בהרבה מאוד שפות , כמו שאפשר לראות באתר http://reactivex.io/languages.html 
  • הרעיון של תבנית התיכנות הזו, הוא שיש לנו אובייקט מסוים, שנגדיר אותו בתור "הנושא", ובנוסף אליו אנחנו מגדירים "צופים" שכל הזמן מסתכלים\עוקבים\צופים על הנושא, ברגע שמשהו בנושא משתנה ( בעגה המקצועית – יש שינוי של State , של מצב )
    אז כל הצופים רואים את השינוי באופן אוטומטי.
  • למה זה טוב ?
    • זה לא מצריך להסתבך עם callbacks
    • זה מאפשר לפתוח "ערוץ מידע" קבוע לכל מיני חיבורים למקורות מידע ( דאטאבייס, API, וכדומה ) כך שברגע ש-"נרשמנו" בתור "צופים" על הנושא, אז מרגע זה, אנחנו משוחררים מלבדוק כל הזמן את המצב של הנושא, אלא רק הגדרנו במקום מסוים, מה קורה כאשר הנושא משנה מצב (state), ומשם ואילך – הטיפול הוא באמצעות ה"צופה" שהגדרנו .

המחשה – Observable

  • ניצור service
  • נייבא פנימה גם את Observable מתוך rxjs/Observable
  • ניצור משתנה שיכיל את המידע, מסוג Observable, ונשתמש ב-syntax של <> כדי להצהיר על הסוג הספציפי שיחזור.
    המשתנה הזה, הוא ה-"צופה", כלומר הוא יכיל פונקציה שתדאג לדווח לנו בכל פעם שיש שינוי ב-state של המידע.
  • ניצור פונקציה שמחזירה את המידע
    • בתוך הפונקציה נשים בתוך המשתנה  מסוג Observable שלנו, אובייקט חדש, מסוג Observable, עם פונקציה שמחזירה מידע
    • לצורך הדוגמא בלבד, נשתמש ב-setTimeout, כדי להחזיר מידע חדש כל X זמן, ובעצם להדגים בזה, כיצד ה"צופה" מרגיש שהמידע השתנה, ומוסיף אותו לסט הנתונים.
  • בקומפוננט
    • נייבא את ה-Service שיצרנו
    • ניצור משתנה שיקבל את התוכן
    • ונרשום פקודה, ש-"נרשמת" לצפיה, בפונקציה של ה-service שמחזירה את הצופה.
    • מה שיקרה הוא שהצופה יחזיר כל פעם מידע ברצף
      כלומר בעצם יצרנו אפשרות ליצור רצף של מידע שמגיע.
--- The service file -----

import { Injectable } from '@angular/core';
import { Observable } from 'rxjs/Observable';


@Injectable()

export class BasicService {
 data:Observable<Array<number>>;

 constructor() {
 }

 getData() {
 this.data = new Observable(observer => {
 setTimeout(()=> {
 observer.next(1);
 },1000);
 setTimeout(()=> {
 observer.next(2);
 },2000);
 setTimeout(()=> {
 observer.next(3);
 },3000);
 setTimeout(()=> {
 observer.next(4);
 },4000);
 setTimeout(()=> {
 observer.complete();
 },5000);
 });

 return this.data;
 }
 
}



----- the Component file -------
import { Component, OnInit } from '@angular/core';
import { BasicService } from './../../services/basicService2/basic.service';


@Component({
 selector: 'app-use-observable2',
 template: `
 <h1>Observable Example</h1>
 <ul>
 <li *ngFor="let i of data">
 {{ i }}
 </li>
 </ul>
 
 `
})
export class UseObservable2Component implements OnInit {

 data:any[] = [];

 constructor(public basicService:BasicService) {
 this.basicService.getData().subscribe(returnedData => {
 console.log(returnedData);
 this.data.push(returnedData);
 });
 }

 ngOnInit() {
 }

}

שיעור 19 באנגולר – Services

מהו Service באנגולר ?

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

איך יוצרים service באנגולר ?

  • ניצור מחלקה חדשה, מקובל לשים services בתיקיה שנקראת services
  • כדי ה- service שלנו יוכל להיות מוזרק לקומפוננטות ( Depency Injection ) , אז אנחנו צריכים לעשות import   של Injectable , שמאפשר למחלקה להיות מוזרקת בהמשך.
  • ובסופו של דבר, נרשום את ה- service ברשימת הספקים הקיימים, שנמצאת במערך ngModule
  • אם עשינו את כל אלו – נוכל להזריק ולהשתמש ב- service בכל קומפוננטה שנרצה.

איך יוצרים service באמצעות כלי שורת הפקודה angular cli ?

  • נקליד :
ng g service MY_SERVICE_NAME

דוגמא בסיסית ל-service באנגולר

  • בקטעי קוד הבאים רואים service פשוט שמחזיר מערך של מידע.
  • ה-service נרשם כספק במערך ה-providers בקובץ app.module.ts ( וכמובן מיובא שם )
  • ה- service מוזרק לתוך קומפוננט ( וכמובן מיובא שם )  בקונסטרקטור
  • המידע מה-service עובר למשתנה בקומפוננט, ומוצג על המסך עם לולאה של אנגולר.
---------- the service file --------------
import { Injectable } from '@angular/core';

@Injectable()

export class BasicService {
 users:string[];

 constructor() {
 this.users = ["Bubu","Koko","Moko"];
 }

 getUsers(){
 return this.users;
 }
}


---------- app.module.ts -----------------

...
...
import { BasicService } from './services/basicService2/basic.service';

...
...
providers: [
 ...
 ...
 
 BasicService
 ],

---- קובץ הקומפוננט --------------------

import { Component, OnInit } from '@angular/core';
import { BasicService } from './../../services/basicService2/basic.service';

@Component({
 selector: 'app-just-another-component',
 template:` 
 
 <h1>Hi</h1>
 <ul>
 <li *ngFor="let user of users">
 {{ user}}
 </li>
 </ul>
 
 `
})
export class JustAnotherComponentComponent implements OnInit {

 users:string[];

 constructor(public basicService:BasicService ) { 

 this.users = this.basicService.getUsers();

 }

 ngOnInit() {
 }

}

 

שיעור 17 ב-ionic, שימוש ב toggleButton

כחלק מרכיבי ה-CSS של ionic , יש גם toggle button, כפתור דו מצבי נחמד.

בקוד הבא אפשר לראות :

  • שימוש בתגית ion-toggle, כדי לשים כפתור דו מצבי על המסך.
  • שימוש ב-[checked] על מנת לקשור אליו משתנה\פונקציה כדי שערכו ישמר.
  • על הדרך , אך ללא קשר, השתמשתי ב- ion-grid – שמאוד דומה לבוטסטראפ, וב-ion-label שמאפשר לשים תויות פשוטות ונחמדות.
<ion-content padding>
 <ion-grid>
 <ion-row>
 <ion-col>
 <ion-label>
 רקע שונה
 </ion-label>
 </ion-col>
 <ion-col>
 <ion-toggle 
 (ionChange)="onToggle($event)" 
 [checked]="checkAltBackground()" ></ion-toggle>
 </ion-col>
 </ion-row>
 </ion-grid>
</ion-content>

 

שיעור 16 ב-ionic – הוספת תפריט צד, שימוש ב MenuController

  • הוספת תפריט צד בנוסף לטאבים, היא מהלך מעט מורכב
  • אציין אותו שלב אחר שלב, ולבסוף אביא את הקוד
  • בתוך app.html נוסיף תגית ion-menu, ובתוכו את הכפתורים הרלוונטים.
  • התגית ion-menu צריכה לבוא עם הגדרה שאומרת לה "היכן להחליף את העמודים" , כדי להגדיר זאת
    • נוסיף לתגית ion-nav סימון רגיל של תבנית אנגולר, כלומר למשל #nav
    • ולתגית ion-menu נוסיף הגדרה [content]="nav"
  • כדי לתת מראה אחיד בתוך התפריט, נשתמש בתגית ion-list, כאשר לכל אחד מהכפתורים נוסיף הגדרת ion-item
  • כמובן צריך להוסיף אירוע click לכל אחד מהכפתורים ב app.component.ts
  • כדי לשלוט בתוך האירוע בעמוד שיוצג, שהוא למעשה עמוד ה-root,
    נשאלת השאלה – איך נקבע את עמוד ה-root ?
    הרי בשלב זה , אנחנו בתוך הקומפוננט הראשון, ה- app.html, אז אנחנו עדין לא יכולים להזריק את NavController, כיוון שהוא עדין לא נוצר ( למרות שיש לו דווקא מתודה נחמדה של setRoot שהייתה יכולה לעזור לנו).
    אז כדי לתת פתרון אחר למטרה שלנו להחליף את עמוד ה-root , אנחנו נשתמש בפונקציה של אנגולר שנקראת ViewChild@,  זו שיטה באנגולר שבה אפשר לגשת לתבנית מסויימת, אחרי שהיא נוצרה, במקרה שלנו, אנחנו ניגש לתפריט אחרי שהוא נוצר, ושם כמובן, נוכל לגשת ל-NavController ולהשתמש במתודה שתאפשר לנו  להגדיר את ה-root.
    כלומר זהו פתרון עוקף שיאפשר לנו להשתמש ב-nav controller.
    הפתרון הזה מתואר בדוקמונטציה בקישור הזה.
  • אחרי שהמשתמש לוחץ על כפתור, אזי אנחנו צריכים לסגור את התפריט, לצורך כך נשתמש באובייקט MenuController, ספציפית במתודה שלו close.
  • כדי להוסיף בעמודים השונים (pages) את סימן התפריט, נוסיף כפתור , עם icon מובנה של ionic שנקרא menu.
  • את הכפתור ב-html, כדאי לעטוף בתגית של ionic שמיועדת לסידור של כפתורים בשורה. היא נקראת ion-buttons, ואפשר להוסיף לה את המאפיין start או end כדי להחליט האם הכפתור ישב בצד ימין או שמאל.
  • כדי להקפיץ את התפריט, נזריק לקלאס הרלוונטי את MenuController , ונשתמש במתודה שלו שנקראת open.
  • אך זה יכול להיות מעצבן מאוד, לו נצטרך בכל עמוד להוסיף את הכפתור, וליצור מתודה עבורו, לצורך כך ישנו קיצור דרך : להוסיף לכפתור התפריט את ההגדרה menuToggle . ואז לא צריך ליצור מתודה, ולייבא וכו'…
---- app.html file -----------------

<ion-menu [content]="nav" >
 <ion-header>
 <ion-toolbar>
 <ion-title>Menu</ion-title>
 </ion-toolbar>
 </ion-header>
 <ion-content>
 <ion-list>
 <button (click)="onLoad(tabsPage)" ion-item>
 <ion-icon name="quote" item-left></ion-icon>
 Quotes
 </button>
 <button ion-item (click)="onLoad(settingsPage)">
 <ion-icon name="settings" item-left></ion-icon>
 Settings
 </button>
 </ion-list>
 </ion-content>
</ion-menu>

<ion-nav [root]="tabsPage" #nav ></ion-nav>



------- app.component.ts file ---------------------

import { Component, ViewChild } from '@angular/core';
import { Platform, NavController, MenuController } from 'ionic-angular';
import { StatusBar } from '@ionic-native/status-bar';
import { SplashScreen } from '@ionic-native/splash-screen';

import { TabsPage } from './../pages/tabs/tabs';
import { SettingsPage } from './../pages/settings/settings';

@Component({
 templateUrl: 'app.html'
})
export class MyApp {
 //rootPage:any = TabsPage;
 tabsPage:any = TabsPage;
 settingsPage:any = SettingsPage;
 @ViewChild('nav') nav:NavController;

 constructor(platform: Platform, statusBar: StatusBar, splashScreen: SplashScreen
 ,private mnuCtrl:MenuController) {
 platform.ready().then(() => {
 // Okay, so the platform is ready and our plugins are available.
 // Here you can do any higher level native things you might need.1
 statusBar.styleDefault();
 splashScreen.hide();
 });
 }

 onLoad(page:any) {
 this.nav.setRoot(page);
 this.mnuCtrl.close();
 }
}

--------- בכל דף שבו מעוניינים בתפריט נוסיף משהו דומה -------------


<ion-header>

 <ion-navbar>
 <ion-buttons end >
 <button ion-buton menuToggle >
 <ion-icon name="menu"></ion-icon>
 </button>
 </ion-buttons>
 <ion-title>favorites</ion-title>
 </ion-navbar>

</ion-header>