四月 2024
1234567
891011121314
15161718192021
22232425262728
2930  

彙整

本校資訊設備財產管理會議(1060518)

日期:106年5月18日

時間:上午 09:40-10:30

出席者:教務主任陳明秀、總務主任蔡坤陵、資訊組長邱昭士、幹事(財產管理人)林燕琇

會議結論:

  • 請資訊組長協助財管人員貼資訊設備財產編號。
    • 請資訊組長列資訊設備清冊及所在位置給財管人員,由財管人員至設備所在位置貼財產編號。
  • 行政電腦:由各行政人員保管、使用。
  • 電腦機房及電腦教室內設備:由資訊組統一管理。
  • 班級電腦、公用電腦:由資訊組長擔任保管人,由實際使用人或使用單位擔任使用人,財管人員須明列每一台電腦所在位置及使用人。
    • 詳細使用人及設備所在位置由資訊組長管理,並提出給財管人員登錄。
  • 筆記型電腦、平板電腦:由專案申請的單位保管、使用,其餘由資訊組統一管理。
  • 教育局撥入之網路設備(含網路交換器、無線基地台、網路電話…):由資訊組統一管理。
  • 一般教室與專科教室內的單槍吊架、液晶投影機、遙控器、單槍布幕、麥克風、擴大機、喇叭、音源線路及轉接頭、連接單槍之線路、電路由總務處派專人管理。
  • 原於舊大樓財產歸資訊組長的設備,因舊大樓已拆,設備已統由總務處收藏至倉庫中,財產改由總務處派專人保管。
  • 因應敬業樓即將於下學期拆除,本學期結束前置於敬206教室待報廢的設備,請資訊組長列清單給財管人員報廢處理。

會後處理情形:

5月18日(四):

  • 上午,於會後,財管人員找一名工友,陪同資訊組長至設備所在位置貼財產編號。(13台網路交換器、1台無線網路控制器、3台行動便利箱、15台平板電腦)
  • 下午,送出上午開會記錄給教務主任、財管人員、總務主任,最後陳閱至校長處。
  • 下午,財管人員親至電腦機房,貼「11 台網路電話、2台液晶顯示器、1台平板電腦充電櫃」財產編號,至電腦教室(二)貼「EVO 原音廣播盒」財產編號。
  • 下午,財管人員請一名工友,協助貼新大樓「19台無線基地台」財產編號。
  • 下午,送出第一波資訊設備財產移轉清單給財管人員。

新北市教育局程式應用研發社群工作坊-Angular 2(1060503~0621)

日期:106年5月3日~6月21日

時間:每週三下午

地點:新北市教研中心

公文與計畫:


課程主題:Angular

講師:林士立老師


【5月3日】:

【學習資源】【5月3日】【5月10日】【5月17日】【5月24日】【5月31日】【6月7日】【6月14日】【6月21日】

課前預習:

開發環境與工具:

安裝開發環境與工具

  • 安裝 nodejs
  • 安裝開發工具 (WebStorm)
  • 安裝 Git
  • 安裝 Chrome 擴充功能:Angular Augury

安裝 Angular CLI

npm install -g @angular/cli //@類似 namespace 功能
ng -v


ng new demo --routing
cd demo
npm install @angular/language-service --save-dev
ng -v

執行專案專屬的 TypeScript 編譯程式

  • .\node_modules\.bin\tsc
  • 編譯 src\main.ts 為 src\main.js
  • -w : 持續監視 src\main.ts,一有變動,就立即編譯

.\node_modules\.bin\tsc src\main -w


【5月10日】:

【學習資源】【5月3日】【5月10日】【5月17日】【5月24日】【5月31日】【6月7日】【6月14日】【6月21日】

課前預習:

更新 Angular CLI

angular-cli 更新到 1.0.2 版了,更新步驟如下:

global 版本更新:

npm uninstall -g @angular/cli
npm cache clean
npm install -g @angular/cli@latest

查看 angular-cli 版本( 專案目錄之外執行 ):
ng -v

————————————————————

舊版 angular-cli 產生的專案內的版本( local )更新:

注意!!
以下指令要在專案根目錄下執行,也會升級其他 package

Linux or Mac
rm -rf node_modules dist

Windows 命令提示字元
rmdir /S/Q node_modules dist

Windows PowerShell
rm -r -fo node_modules,dist

所有作業系統
npm install –save-dev @angular/cli@latest
npm install

單獨升級專案內的 angular-cli

npm uninstall @angular/cli –save-dev
npm install –save-dev @angular/cli

查看 local angular-cli 與 angular 相關 package 版本( 專案目錄下執行 ):
ng -v


使用 Angular 2 開發 TodoMVC 應用程式完整實作教學

操作指令:

ng new todomvc

cd todomvc

code . ==> 啟用 Visual Studio Code,並開啟當前所在的資料夾(todomvc)

cd ..

git clone https://github.com/coolrare/todomvc-template.git

  • 複製 todomvc-template/assets/css 資料夾至 todomvc/src/assets 下
  • 開啟 todomvc-template/index.html 將內容整個複製至 todomvc/src/index.html 內做編輯。
  • 將原 todomvc-template/index.html 中 <head> 中的內容:
    • <title> 取代 原 todomvc/src/index.html 中的 <title>
    • 兩個 <link> 複製至原 todomvc/index.html <head> 中
  • 將原 todomvc-template/index.html 中 <body> 的內容取代 todomvc/src/app/app.component.html 中的內容。

npm start ==> 啟用網頁伺服器 http://localhost:4200,並監視網頁更新情形,一有更新立即重新編譯,並更新網頁

ng g c title

ng g c rooter

ng g pipe filter

ng g service data


課程活動:

講義:Angular 簡介

參考網站:不專業網管筆記 | 林士立老師


實作:

範例程式下載:https://drive.google.com/drive/folders/0B_wx0SuvjnGWd1pyZmY3Zi1memM

參考資料:

操作指令及步驟:

  • ng new toh-demo –routing (注意:routing前有兩個 – 號)
  • 開啟 WebStrom
  • npm start  => 啟用網頁伺服器 http://localhost:4200,並監視網頁更新情形,一有更新立即重新編譯,並更新網頁
  • 範例檔案下載解壓縮至專案根目錄下
  • ng g c navbar (ng generate component navbar) => 產生 src/app/navbar 資料夾

installing component
create src\app\navbar\navbar.component.css
create src\app\navbar\navbar.component.html
create src\app\navbar\navbar.component.spec.ts
create src\app\navbar\navbar.component.ts
update src\app\app.module.ts

  • 將範例檔 heroes.html<nav> (含)網頁內容取代 navbar.component.html 中所有的網頁內容。
  • 將範例檔 heroes.html 下列資料複製至 index.html 相對位置
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/css/bootstrap.min.css">
<script src="https://code.jquery.com/jquery.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/js/bootstrap.min.js"></script>
  • ng g c heroes

installing component
create src\app\heroes\heroes.component.css
create src\app\heroes\heroes.component.html
create src\app\heroes\heroes.component.spec.ts
create src\app\heroes\heroes.component.ts
update src\app\app.module.ts

  • 將範例檔 heroes.html<div class="container"> (不含)網頁內容取代 heroes.component.html 中所有的網頁內容。
  • ng g cl Hero
    installing class
    create src\app\hero.ts
  • 複製 mock-heroes.tssrc/app

修改 heroes.component.html 內容

<!-- 清單 -->
<div class="list-group">
  <a class="list-group-item my-item" *ngFor="let hero of heroes">
    <span>{{ hero.id }}</span>{{ hero.name }}<span class="badge">X</span>
  </a>
</div>
<!-- 清單結束 -->

hero.ts 內容

export class Hero {
  id: number;
  name: string;
}

app.component.html 網頁內容

<app-navbar></app-navbar>
<div class="container">
  <app-heroes></app-heroes>
</div>

Angular 系統運作說明:

main.ts 說明:

import { enableProdMode } from '@angular/core';
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';

import { AppModule } from './app/app.module';
import { environment } from './environments/environment';

if (environment.production) {
  enableProdMode();
}

platformBrowserDynamic().bootstrapModule(AppModule);

app.module.ts 說明:

import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { FormsModule } from '@angular/forms';
import { HttpModule } from '@angular/http';
import { CommonModule } from '@angular/common';
import { AppRoutingModule } from './app-routing.module';

import { AppComponent } from './app.component';
import { NavbarComponent } from './navbar/navbar.component';
import { HeroesComponent } from "./heroes/heroes.component";

@NgModule({
  declarations: [
    AppComponent,
    NavbarComponent,
    HeroesComponent
  ],
  imports: [
    BrowserModule,
    FormsModule,
    HttpModule,
    CommonModule,
    AppRoutingModule
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

app.component.ts 說明:

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

@Component({
  selector: 'app-root',  // HTML Tag
  templateUrl: './app.component.html',  // 樣板網頁置於另一個檔案
/*
  template: `<app-navbar></app-navbar>`,  // 樣板網頁內容置於倒單引號「`
*/
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  title = 'app works!';
}

【5月17日】:

【學習資源】【5月3日】【5月10日】【5月17日】【5月24日】【5月31日】【6月7日】【6月14日】【6月21日】

課前預習:

上課講義:

Angular2 Binding: 組合鍵

keydown.a
keydown.b
keydown.c
keydown.dot
keydown.Spacebar
keydown.meta.Enter  <= meta: Windows Key
keydown.alt.Enter
keydown.control.Enter
keydown.shift.Enter
keydown.meta.o
keydown.meta.s
keydown.meta.f
keydown.escape
keydown.ArrowLeft
keydown.ArrowRight
keydown.ArrowUp
keydown.ArrowDown
keydown.0
keydown.1
keydown.2
keydown.3
keydown.4
keydown.5
keydown.6
keydown.7
keydown.8
keydown.9

使用 keyup 也行,只是觸發時間點不同而已。

課堂練習及習作解答:僅供參考

app.component.html

<h1>{{title}}</h1>
<input type="text" #newurl (keydown.control.enter)="changeUrl(newurl.value)">
<button (click)="changeUrl(newurl.value)">submit</button>
<img [src]="url" [width]="w">
<hr>
寬:{{divx}}<input type="range" min=0 max=200 [value]="divx" style="width: 200px;" [(ngModel)]="divx">
高:{{divy}}<input type="range" min=0 max=200 [value]="divy" style="width: 200px;" [(ngModel)]="divy">
<br>
<div style="border: 1px red solid;" [style.width.px]="divx" [style.height.px]="divy"></div>

app.component.ts

import { Component } from '@angular/core';
@Component({
 selector: 'app-root',
 templateUrl: './app.component.html',
 styleUrls: ['./app.component.css']
})
export class AppComponent {
 title = 'app works!';
 url = 'https://angular.io/resources/images/logos/angular/angular.svg';
 w = 100;
 divx = 100;
 divy = 100;

 changeUrl(newUrl) {
   this.url = newUrl;
 }
}

【5月24日】:

【學習資源】【5月3日】【5月10日】【5月17日】【5月24日】【5月31日】【6月7日】【6月14日】【6月21日】


分享重點:

  • Angular 中的 css 樣式處理
  • NgIf 、 NgFor 、 NgSwitch 家族

上課講義:

Directive 中文參考資料:

參考資料:

上課筆記:

app.component.html

<table border="2">
  <tr>
    <td [attr.colspan]="cols">1</td>
    <td>2</td>
  </tr>
  <tr>
    <td>4</td>
    <td>5</td>
    <td>6</td>
  </tr>
</table>

<br />

<div class="abc"
     [class.active]="active"
     [class.title]="active"></div>

<button (click)="active = !active">{{active}}</button>

<div class="abc active inactive"
     [ngClass]="getObj()"></div>

<textarea [(ngModel)]="msg" *ngIf="true"></textarea>

<textarea [(ngModel)]="msg" *ngIf="false"></textarea>
<textarea [(ngModel)]="msg" [hidden]="true"></textarea>

<button *ngFor="let item of array1" (click)="handle(item)">
  {{item}}
</button>

<br />

<button (click)="color='red'">red</button>
<button (click)="color='blue'">blue</button>

<div *ngIf="color==='red'; then thenblock; else other"></div>

<ng-template #thenblock>
  <div style="background-color: red; width: 100px; height: 100px;"></div>
</ng-template>

<ng-template #other>
  <div style="background-color: blue; width: 100px; height: 100px;"></div>
</ng-template>

app.component.ts

export class AppComponent {
  cols = 2;
  active = true;
  msg = '';
  array1 = ['aa', 'bb', 'cc', 'dd'];
  color = 'red';

  getObj() {
    return {
      active: this.active,
      inactive: !this.active,
      myTitle: true
    };
  }

  handle(m: string) {
    this.msg += this.msg ? (',' + m) : m;
  }

}

【5月31日】:

【學習資源】【5月3日】【5月10日】【5月17日】【5月24日】【5月31日】【6月7日】【6月14日】【6月21日】


上課講義、範例、錄影檔:

實作:

ng g c child

child\child.component.html

<h2>{{ title }}</h2>
<button (click)="send('msg from child');">點我!點我</button>

child\child.component.ts

export class ChildComponent implements OnInit {
  @Input() title = 'default child title';

  @Output() sendmsg = new EventEmitter<string>();

  constructor() { }

  ngOnInit() {
  }

  send(msg) {
    console.log(msg);
    this.sendmsg.emit(msg);
  }

}


ng g c counter-button

counter-button\counter-button.component.html

<button (click)="count();">{{ value }}</button>

counter-button\counter-button.component.ts

export class CounterButtonComponent implements OnInit {
  @Input('step') value = 1;

  @Output('changed') valueChange = new EventEmitter<number>();

  constructor() { }

  ngOnInit() {
  }

  count() {
    this.valueChange.emit(this.value);
  }

}


app.component.html

<app-child
  [title]="'this is new title'"
  (sendmsg)="log($event)">
</app-child>
<br>
<app-counter-button [value]="-2" (changed)="change($event);"></app-counter-button>
{{ counter }}
<app-counter-button [value]="+5" (changed)="change($event);"></app-counter-button>

app.component.ts

counter = 10;
log(e) {
  console.log(e);
}

change(v: number) {
  this.counter += v;
}

作業:

  • 按下方圖塊,圖塊的顏色會顯示在上方
  • 按下方圖塊的按鈕[edit],會出現按鈕[close]及色彩三原色(紅、綠、藍)拉霸,可混色為在其上方的圖塊顏色,原按鈕[edit]會消失。
  • 按下方圖塊的按鈕[close],會出現按鈕[edit],原按鈕[close]及色彩三原色(紅、綠、藍)拉霸會消失。

◎林士立老師作業實作參考:

https://gist.github.com/t301000/fa692be5208abdf6b793e94901c20b57

邱昭士老師作業實作參考:

ng g c color-panel

color-panel\color-panel.component.html

<div style="width: 100px; height: 100px;" [style.backgroundColor]="getMyStyle()" (click)="setStyle()"></div>
<div *ngIf="edit; then thenBlock; else otherBlock"></div>
<ng-template #thenBlock>
  <button (click)="edit=false;">close</button>
  <input type="range" min="0" max="255" style="background-color: red;" [(ngModel)]="color.r">
  <input type="range" min="0" max="255" style="background-color: green;" [(ngModel)]="color.g">
  <input type="range" min="0" max="255" style="background-color: blue;" [(ngModel)]="color.b">
</ng-template>

<ng-template #otherBlock>
  <button (click)="edit=true;">edit</button>
</ng-template>

color-panel\color-panel.component.css

input[type="range"]{
  -webkit-appearance: none;
  overflow:hidden;     /* 限定範圍 */
  width:90px;
  height:15px;
  outline : none;      /* 避免點選會有藍線或虛線 */
  background:none;
}

color-panel\color-panel.component.ts

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

@Component({
  selector: 'app-color-panel',
  templateUrl: './color-panel.component.html',
  styleUrls: ['./color-panel.component.css']
})
export class ColorPanelComponent implements OnInit {
 edit = false;
 @Input() color = {r: 255, g: 255, b: 255};
 @Output() colorSet = new EventEmitter<string>();

 constructor() { }

 ngOnInit() {
 }

 getMyStyle() {
   return `rgb(${this.color.r}, ${this.color.g}, ${this.color.b})`;
 }

 setStyle() {
   this.colorSet.emit(this.getMyStyle());
 }

}

app.component.html

<table border="1">
  <tr>
    <td [attr.colspan]="colors.length">
      <div style="width: 100%; height: 100px;" [style.backgroundColor]="myColor"></div>
    </td>
  </tr>
  <tr style="vertical-align: top;">
    <td *ngFor="let color of colors">
      <app-color-panel [color]="color" (colorSet)="myColor=$event"></app-color-panel>
    </td>
  </tr>
</table>

app.component.ts

export class AppComponent {
  colors = [
    {r: 0, g: 0, b: 0},
    {r: 255, g: 0, b: 0},
    {r: 255, g: 255, b: 0},
    {r: 255, g: 0, b: 255},
    {r: 0, g: 255, b: 0},
    {r: 0, g: 255, b: 255},
    {r: 0, g: 0, b: 255},
  ];
  myColor = `rgb(255, 0, 0)`;

}

參考資料:


【6月7日】:

【學習資源】【5月3日】【5月10日】【5月17日】【5月24日】【5月31日】【6月7日】【6月14日】【6月21日】


上課講義、範例、錄影檔:


【6月14日】:

【學習資源】【5月3日】【5月10日】【5月17日】【5月24日】【5月31日】【6月7日】【6月14日】【6月21日】


上課講義、範例、錄影檔:

實作:

index.html

<!doctype html>
<html>
<head>
  <meta charset="utf-8">
  <title>Tour Of Heroes</title>
  <base href="/">

  <meta name="viewport" content="width=device-width, initial-scale=1">
  <link rel="icon" type="image/x-icon" href="favicon.ico">
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/css/bootstrap.min.css">
  <!--[if lt IE 9]>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv.min.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/respond.js/1.4.2/respond.min.js"></script>
  <![endif]-->
</head>
<body>
  <app-root>Loading...</app-root>

  <script src="https://code.jquery.com/jquery.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/js/bootstrap.min.js"></script>
</body>
</html>

app.component.html

<app-navbar></app-navbar>

<div class="container">
  <router-outlet></router-outlet>
</div>

app-routing.module.ts

import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';

import { HeroesComponent } from './heroes/heroes.component';
import { DashboardComponent } from './dashboard/dashboard.component';
import { PageNotFoundComponent } from './page-not-found/page-not-found.component';
import { HeroDetailComponent } from './hero-detail/hero-detail.component';

const routes: Routes = [
  {
    path: '',
    redirectTo: 'heroes',
    pathMatch: 'full'
  },
  { path: 'heroes', component: HeroesComponent },
  { path: 'heroes/:id', component: HeroDetailComponent },
  { path: 'dashboard', component: DashboardComponent },
  { path: '**', component: PageNotFoundComponent }
];

@NgModule({
  imports: [RouterModule.forRoot(routes)],
  exports: [RouterModule]
})
export class AppRoutingModule { }

hero.service.ts

import { Injectable } from '@angular/core';
import { Headers, Http, RequestOptions, Response } from '@angular/http';

import { Hero } from './hero';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/catch';
import 'rxjs/add/operator/do';
import 'rxjs/add/observable/throw';
import 'rxjs/add/observable/of';

@Injectable()
export class HeroService {
  baseUrl = '/api/heroes';

  constructor(private http: Http) { }

  getHeroes(): Observable<Hero[]> {
    return this.http.get(this.baseUrl)
              .map((res: Response) => res.json().data || {})
              .catch(this.handleError);
  }

  addHero(name: string): Observable<Hero> {
    const headers = new Headers({
      'Content-Type': 'application/json'
    });
    const options = new RequestOptions({headers});
    return this.http.post(this.baseUrl, {name}, options)
              .map((res: Response) => res.json().data)
              .catch(this.handleError);
  }

  deleteHero(id: number): Observable<any> {
    return this.http.delete(`${this.baseUrl}/${id}`)
              .map((res: Response) => null)
              .catch(this.handleError);
  }

  getHero(id: number): Observable<Hero> {
    return this.http.get(`${this.baseUrl}/${id}`)
              .map((res: Response) => res.json().data || {})
              .catch(this.handleError);
  }

  updateHero(id: number, name: string): Observable<any> {
    const headers = new Headers({
      'Content-Type': 'application/json'
    });
    const options = new RequestOptions({headers});
    return this.http.put(`${this.baseUrl}/${id}`, {id, name}, options)
              .map(() => null)
              .catch(this.handleError);
  }

  searchHero(keyword: string): Observable<Hero[]> {
    return this.http.get(`${this.baseUrl}/?name=${keyword}`).do(() => console.log(keyword))
               .map((res: Response) => res.json().data as Hero[] || [])
               .catch(this.handleError);
  }

  private handleError(error: Response | any): Observable<any> {
    // console.log(error);
    let errMsg: string;
    if (error instanceof Response) {
      const body = error.json() || '';
      const err = body.error || JSON.stringify(body);
      errMsg = `${error.status} - ${error.statusText || ''} ${err}`;
    } else {
      errMsg = error.message ? error.message : error.toString();
    }
    console.error(errMsg);
    return Observable.throw(errMsg);
  }
}

hero.ts

export class Hero {
  id: number;
  name: string;
}

heroes.data.ts

import { InMemoryDbService } from 'angular-in-memory-web-api';
import { Hero } from './hero';

export class HeroDB implements InMemoryDbService {
  createDb(): {[key: string]: Hero[]} {
    const heroes: Hero[] = [
      {id: 11, name: 'Mr. Nice'},
      {id: 12, name: 'Narco'},
      {id: 13, name: 'Bombasto'},
      {id: 14, name: 'Celeritas'},
      {id: 15, name: 'Magneta'},
      {id: 16, name: 'RubberMan'},
      {id: 17, name: 'Dynama'},
      {id: 18, name: 'Dr IQ'},
      {id: 19, name: 'Magma'},
      {id: 20, name: 'Tornado'}
    ];
    return {heroes};
  }
}

heroes\heroes.component.html

<div class="page-header">
  <h1>My Heroes</h1>
</div>

<app-new-hero (createHero)="addHero($event)"></app-new-hero>
<hr />

<!-- 清單 -->
<div class="list-group">
  <a class="list-group-item my-item"
      *ngFor="let hero of heroes"
      (click)="selectedHero = hero"
      [class.active]="selectedHero === hero">
    <span>{{ hero.id }}</span>{{ hero.name }}
    <span class="badge" (click)="deleteHero(hero); $event.stopPropagation()"> X </span>
  </a>
</div>
<!-- 清單結束 -->
<div *ngIf="errorMessage">{{ errorMessage }}</div>
<app-mini-detail [hero]="selectedHero" *ngIf="selectedHero"></app-mini-detail>

heroes\heroes.component.ts

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

import { Hero } from '../hero';
import { HeroService } from '../hero.service';

@Component({
  selector: 'app-heroes',
  templateUrl: './heroes.component.html',
  styleUrls: ['./heroes.component.css']
})
export class HeroesComponent implements OnInit {
  heroes: Hero[] = [];
  selectedHero: Hero = null;
  errorMessage: string = null;

  constructor(private heroService: HeroService) { }

  ngOnInit() {
    this.heroService.getHeroes()
        .subscribe(
          heroes => this.heroes = heroes,
          this.showError.bind(this)
        );
  }

  addHero(name: string) {
    this.heroService.addHero(name)
        .subscribe(
          hero => this.heroes.push(hero),
          this.showError.bind(this)
        );
  }

  deleteHero(hero: Hero) {
    this.heroService.deleteHero(hero.id)
        .subscribe(
          () => {
            this.heroes = this.heroes.filter(item => item !== hero);
            this.resetSelectedHero(hero);
          },
          this.showError.bind(this)
        );
  }

  private resetSelectedHero(hero: Hero) {
    if (this.selectedHero && this.selectedHero === hero) {
      this.selectedHero = null;
    }
  }

  private showError(error: string) {
    this.errorMessage = error;
  }

}

new-hero\new-hero.component.html

<div class="form-inline">
  <div class="form-group">
    <label for="name">Hero Name: </label>
    <input type="text" class="form-control" id="name"
           [placeholder]="hintWord" [(ngModel)]="name"
           (keydown.enter)="addHero()">
  </div>
  <button class="btn btn-primary"
          (click)="addHero()" [disabled]="!name.trim()">新增</button>
</div>

new-hero\new-hero.component.ts

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

@Component({
  selector: 'app-new-hero',
  templateUrl: './new-hero.component.html',
  styleUrls: ['./new-hero.component.css']
})
export class NewHeroComponent implements OnInit {
  name = '';
  hintWord = 'New Hero\'s name';
  @Output() createHero = new EventEmitter<string>();

  constructor() { }

  ngOnInit() {
  }

  addHero() {
    const name = this.name.trim();
    if (name) {
      this.createHero.emit(name);
      this.name = '';
    }
  }
}

mini-detail\mini-detail.component.html

<h2>{{ hero.name }} is my hero.</h2>
<div class="btn btn-info" (click)="goDetail()">View Details</div>

mini-detail.component.ts

import { Component, Input, OnInit } from '@angular/core';
import { Hero } from '../hero';
import { Router } from '@angular/router';

@Component({
  selector: 'app-mini-detail',
  templateUrl: './mini-detail.component.html',
  styleUrls: ['./mini-detail.component.css']
})
export class MiniDetailComponent implements OnInit {
  @Input() hero: Hero;

  constructor(private router: Router) { }

  ngOnInit() {
  }

  goDetail() {
    this.router.navigate(['/heroes', this.hero.id]);
  }

}

navbar\navbar.component.html

<nav class="navbar navbar-inverse" role="navigation">
  <div class="container">
    <!-- Brand and toggle get grouped for better mobile display -->
    <div class="navbar-header">
      <button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-ex1-collapse">
        <span class="sr-only">Toggle navigation</span>
        <span class="icon-bar"></span>
        <span class="icon-bar"></span>
        <span class="icon-bar"></span>
      </button>
      <span class="navbar-brand glyphicon glyphicon-text-background"></span>
    </div>

    <!-- Collect the nav links, forms, and other content for toggling -->
    <div class="collapse navbar-collapse navbar-ex1-collapse">
      <ul class="nav navbar-nav">
        <li routerLinkActive="active" [routerLinkActiveOptions]="{exact: true}">
        <!-- 路由連結 (不加上中括號的屬性繫結,只能繫結固定的字串資料) -->
          <a [routerLink]="['/']">Home</a>
        </li>
        <li routerLinkActive="active">
          <a [routerLink]="['/dashboard']">Dashboard</a>
        </li>
        <li routerLinkActive="active">
          <a [routerLink]="['/heroes']">Heroes</a>
        </li>
      </ul>
    </div><!-- /.navbar-collapse -->
  </div>
</nav>

【6月21日】:

【學習資源】【5月3日】【5月10日】【5月17日】【5月24日】【5月31日】【6月7日】【6月14日】【6月21日】


上課講義、範例、錄影檔:

路由說明:

const routes: Routes = [
  //{ path: '', redirectTo: 'heroes', pathMatch: 'full'}, //pathMatch 預設值為 'prefix'
  {path: 'heroes', component: HeroesComponent},
  {path: 'heroes/hello', component: HeroHelloComponent}, //一定要擺在 'heroes/:id' 之前,否則會永遠比對不到,因為系統會誤認:id='hello'
  {path: 'heroes/:id', component: HeroDetailComponent},
  {path: 'dashboard', component: DashboardComponent},
  {path: '**', component: PageNotFoundComponent}
];

實作:

安裝 angular-in-memory-web-api

  • npm i angular-in-memory-web-api –save-dev
  • angular2系列教程(八)In-memory web api、HTTP服务、依赖注入、Observable

hero.service.ts

import { Injectable } from '@angular/core';
import { Headers, Http, RequestOptions, Response } from '@angular/http';

import { Hero } from './hero';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/catch';
import 'rxjs/add/operator/do';
import 'rxjs/add/observable/throw';
import 'rxjs/add/observable/of';

@Injectable()
export class HeroService {
  baseUrl = '/api/heroes';

  constructor(private http: Http) { }

  getHeroes(): Observable<Hero[]> {
    return this.http.get(this.baseUrl)
              .map((res: Response) => res.json().data || {})
              .catch(this.handleError);
  }

  addHero(name: string): Observable<Hero> {
    const headers = new Headers({
      'Content-Type': 'application/json'
    });
    const options = new RequestOptions({headers});
    return this.http.post(this.baseUrl, {name}, options)
              .map((res: Response) => res.json().data)
              .catch(this.handleError);
  }

  deleteHero(id: number): Observable<any> {
    return this.http.delete(`${this.baseUrl}/${id}`)  // this.baseUrl + '/' + id
              .map((res: Response) => null)
              .catch(this.handleError);
  }

  getHero(id: number): Observable<Hero> {
    return this.http.get(`${this.baseUrl}/${id}`)
              .map((res: Response) => res.json().data || {})
              .catch(this.handleError);
  }

  updateHero(id: number, name: string): Observable<any> {
    const headers = new Headers({
      'Content-Type': 'application/json'
    });
    const options = new RequestOptions({headers});
    return this.http.put(`${this.baseUrl}/${id}`, {id, name}, options)
              .map(() => null)
              .catch(this.handleError);
  }

  searchHero(keyword: string): Observable<Hero[]> {
    return this.http.get(`${this.baseUrl}/?name=${keyword}`).do(() => console.log(keyword))
               .map((res: Response) => res.json().data as Hero[] || [])
               .catch(this.handleError);
  }

  private handleError(error: Response | any): Observable<any> {
    // console.log(error);
    let errMsg: string;
    if (error instanceof Response) {
      const body = error.json() || '';
      const err = body.error || JSON.stringify(body);
      errMsg = `${error.status} - ${error.statusText || ''} ${err}`;
    } else {
      errMsg = error.message ? error.message : error.toString();
    }
    console.error(errMsg);
    return Observable.throw(errMsg);
  }
}

heroes.data.ts

import { InMemoryDbService } from 'angular-in-memory-web-api';
import { Hero } from './hero';

export class HeroDB implements InMemoryDbService {
  const HEROES: Hero[] = [
      {id: 11, name: 'Mr. Nice'},
      {id: 12, name: 'Narco'},
      {id: 13, name: 'Bombasto'},
      {id: 14, name: 'Celeritas'},
      {id: 15, name: 'Magneta'},
      {id: 16, name: 'RubberMan'},
      {id: 17, name: 'Dynama'},
      {id: 18, name: 'Dr IQ'},
      {id: 19, name: 'Magma'},
      {id: 20, name: 'Tornado'}
    ];
 createDb(): {
   return {heroes: this.HEROES};
 }
}

heroes\heroes.component.html

<div class="page-header">
  <h1>My Heroes</h1>
</div>

<app-new-hero (createHero)="addHero($event)"></app-new-hero>
<hr />

<!-- 清單 -->
<div class="list-group">
  <a class="list-group-item my-item"
      *ngFor="let hero of heroes"
      (click)="selectedHero = hero"
      [class.active]="selectedHero === hero">
    <span>{{ hero.id }}</span>{{ hero.name }}
    <span class="badge" (click)="deleteHero(hero); $event.stopPropagation()"> X </span>
  </a>
</div>
<!-- 清單結束 -->
<div *ngIf="errorMessage">{{ errorMessage }}</div>
<app-mini-detail [hero]="selectedHero" *ngIf="selectedHero"></app-mini-detail>

heroes\heroes.component.ts

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

import { Hero } from '../hero';
import { HeroService } from '../hero.service';

@Component({
  selector: 'app-heroes',
  templateUrl: './heroes.component.html',
  styleUrls: ['./heroes.component.css']
})
export class HeroesComponent implements OnInit {
  heroes: Hero[] = [];
  selectedHero: Hero = null;
  errorMessage: string = null;

  constructor(private heroService: HeroService) { }

  ngOnInit() {
    this.heroService.getHeroes()
        .subscribe(
          heroes => this.heroes = heroes, //成功 success ==> onNext
          this.showError.bind(this)       //失敗 error   ==> onError
                                          //已完成 completed ==> onCompleted
        );
  }

  addHero(name: string) {
    this.heroService.addHero(name)
        .subscribe(
          hero => this.heroes.push(hero),
          this.showError.bind(this)
        );
  }

  deleteHero(hero: Hero) {
    this.heroService.deleteHero(hero.id)
        .subscribe(
          () => {
            this.heroes = this.heroes.filter(item => item !== hero);
            this.resetSelectedHero(hero);
          },
          this.showError.bind(this)
        );
  }

  private resetSelectedHero(hero: Hero) {
    if (this.selectedHero && this.selectedHero === hero) {
      this.selectedHero = null;
    }
  }

  private showError(error: string) {
    this.errorMessage = error;
  }

}

app.module.ts

import { InMemoryWebApiModule } from 'angular-in-memory-web-api';
import { HeroService } from './hero.service';
import { HeroDB } from './heroes.data';

@NgModule({
  declarations: [
   ...
  ],
  imports: [
    ...
    HttpModule,
    InMemoryWebApiModule.forRoot(HeroDB, {delay: 500}), // must after HttpModule, default delay 500ms
    AppRoutingModule
  ],
  providers: [HeroService],
  bootstrap: [AppComponent]
})
export class AppModule { }

【學習資源】:

【學習資源】【5月3日】【5月10日】【5月17日】【5月24日】【5月31日】【6月7日】【6月14日】【6月21日】

上課講義:

投影片:Angular 2 新手急救站


投影片:Angular 2 開發實戰:進階開發篇 – RxJS 新手入門



【網路資源】

活動照片:

106年5月份三重區資訊組長會議暨成長研習

日期:106年5月16日

地點:仁愛國小電腦教室

會議暨成長研習規劃:

工作報告與活動情形:

  • 賴新田組長下學年度確定不再接任仁愛國小資訊組長,仁愛國小因而也不再接任資訊中心。
    • 資訊中心的經費是採年度配撥,所以下學期接任資訊中心的學校,仍可在本校進行活動。
  • Acer L4620、Z430,仁愛國小有提供映像檔僅各校使用。
  • 對於八期電腦設備,有任何採購建議的請提出:
    • 正義國小:建議採購筆電。

二重國小分享「資安線上稽核填報作法及磨課師教學心得」:

資安線上稽核填報作法:(康組長)

  • 教育部國民中小學資訊安全管理系統
  • 第一次做,逐條認真做,每天花1-2小時,一天最多只做 3 條,約做 30天。
  • 第二次做,各條僅做微修,只須花 30 分鐘,就可大致完成。
  • 可先參照其他學校或局裡提供的文件修改成自己學校的文件。
  • 教育部全國國中小學資訊安全管理系統講習(學校)
    • 研習檔案全部.zip

MOOCs磨課師與均一教育平台教學心得:(梁家福老師)

簡報檔:磨課師與均一教育平台(仁愛國小分享)

  • 接專案固然辛苦,但過程中會有所得,且可為學校爭取到設備和經費。
  • 什麼是磨課師(MOOCs)?
  • 磨課師的教學理念
    • 磨課師學習平台
  • 磨課師的教學理念
    • 線上學習(Online Learning)
    • 自調式學習(Self-Paced Learning)
    • 精熟學習(Mastery Learning)
    • 補教教學(Remedial Teaching)
  • 磨課師課程目的與教學策略
  • 課堂實施磨課師範例
    • 教學設計與實施方式
      • 課前(中)自學 <= 線上學習
      • 課堂學習 <= 自主學習
      • 課堂討論 <= 補救教學
      • 課後總結
      • 課後評量
  • 網路線上學習平台

碧華國小分享「如何在 Scratch 2.0 角色造型上輸入中文字」

參考網址:http://wdpsestea.blogspot.tw/2017/05/scratch2.html (scratch2背景輸入中文 | 陳國全夢幻天地 Blog)

scratch2不管是win或是linux下都無法輸入中文字,經過新北市烜誠(三多國小)和清賢(復興國小)老師的努力,終於可以輸入中文了。烜誠老師還把積木文字放大,更適合國小學生使用。感謝烜誠和清賢老師的努力。

檔案下載位置(裡面有for linux 和for win二個版本)
下載後,解壓㜚把scratch2目錄下的Scratch.swf替換(建議先備份),即可使用了,有更新版需再做一次。
使用時記得字型要選 Donegal
新北市E學園中的epc有win下的免安裝版,也歡迎下載使用。

安裝方法:

  • 安裝好 Scratch 2.0 後,將下載回去的 Scratch.swf 覆蓋掉原安裝目錄下的 Scratch.swf 即完成,有更新版需再做一次。。
  • Scratch.swf 下載路徑:

「WanaCrypt0r 2.0 勒索病毒」解救之道

「WanaCrypt0r 2.0 攻擊系統漏洞」資安警訊

解救之道:

盡速更新 KB3150513 避免遭受 DoublePulsar 攻擊

【資安威脅】因應WannaCrypt攻擊,微軟官方公布Windows Server 2003及XP修復程式

雖然微軟已經停止支援Windows Server 2003及XP等作業系統的漏洞修補許久,但尚有許多客戶仍使用已不支援之Window版本,為了因應此次WannaCrypt勒索軟體大量攻擊之特殊狀況,微軟破例提供以下數項作業系統之修補程式,若有使用以下作業系統之使用者可至連結中下載修補程式,以免遭受病毒攻擊。
修補程式下載連結:https://blogs.technet.microsoft.com/msrc/2017/05/12/customer-guidance-for-wannacrypt-attacks/

漏洞/資安訊息警訊-WanaCrypt0r 2.0 勒索病毒 (1060513)

行政院國家資通安全會報技術服務中心
漏洞/資安訊息警訊

發布編號 NCCST-ANA-2017-0051 發布時間 Sat May 13 12:55:18 CST 2017
事件類型 公告資訊 發現時間 Sat May 13 00:00:00 CST 2017
警訊名稱 近期勒索軟體WannaCry活動頻繁,請立即更新作業系統與防毒軟體,並注意平時資料備份作業
內容說明 近期加密勒索軟體WannaCry(WanaCrypt0r 2.0) 的新型變種勒索病毒正利用 Windows 漏洞(MS17-010漏洞)肆虐,受感染的電腦將會有大量檔案被加密,並且要求高價比特幣贖金。

此波勒索軟體攻擊是利用微軟伺服器訊息區塊(SMB)協定存在數個安全漏洞,台灣受影響的電腦以 Windows XP/Vista/7/8/8.1居多,作業系統請立刻進行 Windows Update 檢查並安裝更新。

影響平台 Windows XP

Windows Vista

Windows 7

Windows 8.1

Windows RT 8.1

Windows 10

Windows Server 2008

Windows Server 2008 R2

Windows Server 2012

Windows Server 2012 R2

Windows Server 2016

影響等級
建議措施 1. 確實持續更新電腦的作業系統、應用程式及防毒軟體等至最新版本。

2. 定期備份電腦上的檔案及演練資料還原程序。

3. 如不幸受到感染,請立即將受害電腦的網路連線及外接儲存裝置拔除,並關閉受害電腦無線網路。建議在清除惡意軟體前不要開啟任何檔案,或變更檔案存放位置。

參考資料 針對微軟伺服器訊息區塊(SMB)協定存在數個安全漏洞相關說明,可參考106/4/27發布之NCCST-ANA-2017-0046警訊。