2016年12月25日 星期日

Package an Angular CLI Application into Electron

Package an Angular CLI Application into Electron | Bruno d'Auria

Electron Tutorial - YouTube

Packaging and distributing your electron/angular 2 desktop apps. - YouTube

electron-userland/electron-packager: Package and distribute your Electron app with OS-specific bundles (.app, .exe etc) via JS or CLI

使用 electron-packager 時可能會出現不知道 electron 版本的問題,在下指令時指定即可:

electron-packager dist --asar --platform=linux --arch=x64 --version=1.4.13

指令下在 angular-cli project 根目錄

先用 ng build 產出 dist 目錄(參數可省略)
 ng build --prod --aot=true -sm=false
--asar:保護原始碼不會被直接看到(需要安裝 asar :npm install -g asar)

--platform=win32 可編譯成 windows 的程式,不過要裝 wine 才可以

electron-userland/electron-builder: A complete solution to package and build a ready for distribution Electron app with “auto update” support out of the box

electron-builder 是另一套打包工具,不過我沒用過....

electron 官網文件:Documentation - Electron

electron type 定義檔:@types/electron


electron-forge  可以打包成 deb / rpm / zip ..... 等檔案格式

2016年12月19日 星期一

Libraries.io : 找 library 的一個好地方

Search for angular2 - Libraries.io

Search for angular 2 - Libraries.io

關鍵字分別是:angular2 與 angular 2

angular2-modal:不錯的 modal 套件,還有產生器可用

Angular2 modal demo application

shlomiassaf/angular2-modal: Angular2 Modal / Dialog window

其中 bootstrap plugin 還有產生器可用喔

HTML5 Drag and Drop file upload

一系列4篇文章:



Demo

Code

Create a MEAN app with Angular 2 and Docker Compose

Create a MEAN app with Angular 2 and Docker Compose | Scotch

重點在 docker 與 docker-compose ....

2016年12月18日 星期日

JavaScript — Observables Under The Hood

JavaScript — Observables Under The Hood

雖然後面的 code 看不太懂,不過前面的比喻還蠻貼切的,希望以後能完全看懂....

angular2 讀取 excel 資料表 part 2

上一篇

這次安裝 typescript wrapper,angular-cli.json 不用改了


1:  /* app.component.ts */  
2:    
3:  import { Component } from '@angular/core';  
4:    
5:  @Component({  
6:   selector: 'app-root',  
7:   templateUrl: './app.component.html',  
8:   styleUrls: ['./app.component.css']  
9:  })  
10:  export class AppComponent {  
11:    
12:   title = 'app works!';  
13:   dropzoneStyle: any = null;  
14:    
15:   reader: FileReader = new FileReader();  
16:   files: FileList = null;  
17:    
18:   workBook: IWorkBook = null;  
19:   workSheetNames: string[] = [];  
20:   workSheets: { [sheet: string]: IWorkSheet } = null;  
21:   currentWorkSheet: IWorkSheet = null;  
22:   currentData: any[]=[];  
23:    
24:   constructor() {  
25:    this.reader.onload = this.setReaderOnloadHandler();  
26:   }  
27:    
28:   /**  
29:    * drop event handler  
30:    *  
31:    * @param e  
32:    */  
33:   readFile(e: DragEvent): void {  
34:    e.stopPropagation();  
35:    e.preventDefault();  
36:    
37:    this.workBook = null;  
38:    this.workSheetNames = [];  
39:    this.workSheets = null;  
40:    this.currentWorkSheet = null;  
41:    this.currentData = [];  
42:    
43:    let files = e.dataTransfer.files;  
44:    this.files = files;  
45:    // console.log(e, files);  
46:    this.dropzoneStyle = {borderColor: 'green'};  
47:    
48:    // 取得第一個檔案  
49:    let file = files[0];  
50:    
51:    this.reader.readAsBinaryString(file);  
52:   }  
53:    
54:   /**  
55:    * dragover event handler  
56:    *  
57:    * @param e  
58:    */  
59:   onDragOver(e: DragEvent): void {  
60:    e.stopPropagation();  
61:    e.preventDefault();  
62:    
63:    this.dropzoneStyle = {borderColor: 'red'};  
64:   }  
65:    
66:   /**  
67:    * 回傳 FileReader onload handler  
68:    *  
69:    * @returns {()=>undefined}  
70:    */  
71:   private setReaderOnloadHandler() {  
72:    return () => {  
73:     let data = this.reader.result;  
74:     try {  
75:      this.workBook = read(data, {type: 'binary'});  
76:     } catch (err) {  
77:      console.log('檔案格式錯誤:', err);  
78:      return;  
79:     }  
80:     this.workSheetNames = this.workBook.SheetNames;  
81:     this.workSheets = this.workBook.Sheets;  
82:    }  
83:   }  
84:    
85:   /**  
86:    * 載入資料表內容  
87:    *  
88:    * @param sheetName  
89:    */  
90:   loadSheetData(sheetName: string): void {  
91:    this.currentWorkSheet = this.workSheets[sheetName];  
92:    
93:    /**  
94:     * header : 0 => 標題欄位名(內容)當 key 產生物件 => default  
95:     * header : 1 => 標題欄位名(內容)為第一個陣列,第二個陣列以後是資料,數字索引  
96:     * header : 'A' => 標題欄位名(字母)當 key 產生物件,第一個物件是標題欄位名(內容),第二個物件以後是資料  
97:     */  
98:    this.currentData = utils.sheet_to_json(this.currentWorkSheet, {header: 1});  
99:   }  
100:  }  
101:    
102:    
103:  /* app.component.html */  
104:    
105:  <div id="drop"  
106:   style="height: 200px;width: 300px;border: dashed gray 3px;"  
107:   [ngStyle]="dropzoneStyle"  
108:   (dragover)="onDragOver($event)"  
109:   (drop)="readFile($event)" >  
110:   Drop here....  
111:  </div>  
112:    
113:  資料表:  
114:  <ul>  
115:   <li *ngFor="let sheet of workSheetNames" (click)="loadSheetData(sheet)">{{ sheet }}</li>  
116:  </ul>  
117:    
118:  currentData  
119:  <div>  
120:   <div *ngFor="let row of currentData;let first = isFirst">  
121:    <span *ngFor="let cell of row">{{cell}}</span> |   
122:   </div>  
123:  </div>  
124:    
125:    

Typescript — Integrate jQuery Plugin in your Project

Typescript — Integrate jQuery Plugin in your Project – Medium

一個在 angular-cli 下新增自定義 type 的例子

Angular 2 — Take Advantage Of The exportAs Property

Angular 2 — Take Advantage Of The exportAs Property

雖然不太有機會自己寫 directive,不過很少看到 exportAs 的例子說....

exportAs ==> 將 instance export 給樣板參考變數

就像:

#f="ngForm"

Angular 2 : Deal with Different Form Controls Cheat Sheet

Angular 2 — Deal with Different Form Controls Cheat Sheet — Template vs Model

收下來參考

Persisting user authentication with BehaviorSubject in Angular

Persisting user authentication with BehaviorSubject in Angular

利用 BehaviorSubject 取得最近一次的值 或 初始值的特性,讓寫法簡潔許多。

最好將 Observable 利用 share(),避免多個 subscriber 時的問題。(文末有說明)

External JavaScript dependencies in Typescript and Angular 2

External JavaScript dependencies in Typescript and Angular 2 - Rick Strahl's Web Log

當使用的套件沒有 type 定義檔時真的很傷腦筋.....

文章中幾種方式可以嘗試看看

angular2 讀取 excel 資料表

SheetJS/js-xlsx: XLSX / XLSM / XLSB / XLS / SpreadsheetML (Excel Spreadsheet) / ODS parser and writer

@types/xlsx

Demo: JS-XLSX Live Demo

typescript wrapper:(還沒試過)

DxCx/ts-xlsx: A working XLSX Library for typescript (Rebuild of the original xlsx): https://github.com/SheetJS/js-xlsx/

drag and drop 參考資料:
康廷數位: HTML5 支援拖曳/置放(Drag and Drop)行為
HTML ondragover Event Attribute
HTML5 Drag Files into the Browser from the Desktop
How to Use HTML5 File Drag and Drop
Pro HTML5 Programming: Chapter 9 | Working with HTML5 Drag-and-Drop
HTML Drag and Drop API - Web APIs | MDN

ng2匯入外部函式庫的幾種方法:

External JavaScript dependencies in Typescript and Angular 2 - Rick Strahl's Web Log


安裝套件:

npm install xlsx --save
npm install @types/xlsx --save-dev

程式碼:

angular-cli.json

    "scripts": [  
     "../node_modules/xlsx/dist/ods.js",  
     "../node_modules/xlsx/dist/xlsx.full.min.js"  
    ]  

app.component.ts

1:  import { Component, ViewChild } from '@angular/core';  
2:  import { IWorkBook, IWorkSheet } from 'xlsx';  
3:    
4:  // declare var XLSX: any;  
5:  let XLSX = window['XLSX'];  
6:    
7:  @Component({  
8:   selector: 'app-root',  
9:   templateUrl: './app.component.html',  
10:   styleUrls: ['./app.component.css']  
11:  })  
12:  export class AppComponent {  
13:    
14:   title = 'app works!';  
15:   dropzoneStyle: any = null;  
16:   reader: FileReader = new FileReader();  
17:   files: FileList = null;  
18:   workBook: IWorkBook = null;  
19:   workSheetNames: string[] = [];  
20:   workSheets: { [sheet: string]: IWorkSheet } = null;  
21:   currentWorkSheet: IWorkSheet = null;  
22:   currentData: any[]=[];  
23:    
24:   constructor() {  
25:    this.reader.onload = this.setReaderOnloadHandler();  
26:   }  
27:    
28:   readFile(e: DragEvent) {  
29:    e.stopPropagation();  
30:    e.preventDefault();  
31:    let files = e.dataTransfer.files;  
32:    this.files = files;  
33:    console.log(e, files);  
34:    this.dropzoneStyle = {borderColor: 'green'};  
35:    
36:    // 取第一個檔  
37:    let file = files[0];  
38:    
39:    this.reader.readAsBinaryString(file);  
40:   }  
41:    
42:   onDragOver(e: DragEvent) {  
43:    e.stopPropagation();  
44:    e.preventDefault();  
45:    
46:    this.dropzoneStyle = {borderColor: 'red'};  
47:   }  
48:    
49:   private setReaderOnloadHandler() {  
50:    return () => {  
51:     let data = this.reader.result;  
52:     this.workBook = XLSX.read(data, {type: 'binary'});  
53:     this.workSheetNames = this.workBook.SheetNames;  
54:     this.workSheets = this.workBook.Sheets;  
55:     this.currentWorkSheet = this.workSheets[this.workSheetNames[0]];//this.workSheets['評量成績'];  
56:     /**  
57:      * header : 0 => 標題欄位名(內容)當 key 產生物件 => default  
58:      * header : 1 => 標題欄位名(內容)為第一個陣列,第二個陣列以後是資料,數字索引  
59:      * header : 'A' => 標題欄位名(字母)當 key 產生物件,第一個物件是標題欄位名(內容),第二個物件以後是資料  
60:      */  
61:     this.currentData = XLSX.utils.sheet_to_json(this.currentWorkSheet, {header: 1});;  
62:    }  
63:   }  
64:  }  
65:    










app.component.html

1:  <div id="drop"  
2:   style="height: 200px;width: 300px;border: dashed gray 3px;"  
3:   [ngStyle]="dropzoneStyle"  
4:   (dragover)="onDragOver($event)"  
5:   (drop)="readFile($event)" >  
6:   Drop here....  
7:  </div>  
8:  <hr />  
9:  files  
10:  <pre>{{files | json}}</pre>  
11:  <hr />  
12:  workBook  
13:  <pre>{{workBook | json}}</pre>  
14:  <hr />  
15:  workSheetNames  
16:  <pre>{{workSheetNames | json}}</pre>  
17:  <hr />  
18:  workSheets  
19:  <pre>{{workSheets | json}}</pre>  
20:  <hr />  
21:  currentWorkSheet  
22:  <pre>{{currentWorkSheet | json}}</pre>  
23:  <hr />  
24:  currentData  
25:  <pre>{{currentData | json}}</pre>  
26:    
27:    

2016年12月3日 星期六

Angular 2 Lifecycle Hooks

My Right To Code - Angular 2 Lifecycle Hooks

有一段短片可以觀察 lifecycle hook 的順序

  1. constructor
  2. OnChanges
  3. OnInit
  4. DoCheck
  5. AfterContentInit
  6. AfterContentChecked
  7. AfterViewInit
  8. AfterViewChecked
  9. OnDestroy
參考: