2016年5月22日 星期日

Angular2.0 快速開發初體驗

 雖然Angular 1.0 邁向2.0已經有一段的時間了,他們終於釋出正式版囉… 結果不出所料和先前測試版的設定有一點不一樣,好在不是大改…  不然就是悲劇收場。

一、NPM 安裝套件要更到最新版
更新npm 的語法
npm install npm -g
 
筆者一直更新npm套件後,檢查版本均為1.4.28,所以無法成功下戴相關

angular2的套件,最後大絕招直接把原本下戴的套件直接殺了,預設路徑C:\Program Files (x86)\nodejs\node_modules ,然後到暫存檔C:\Users\RDCP01\AppData\Local\Temp 把下戴的npm更新包,重新解壓縮到預設路徑即可…  終於可以更新了… 

 

二、架設Angular的環境
官網上說明很清楚如何先加入哪些設定檔,以下資料夾內容如下展示


Package.json : 下戴相依性的套件
{
  "name": "angular2-quickstart",
  "version": "1.0.0",
  "scripts": {
    "start": "tsc && concurrently \"npm run tsc:w\" \"npm run lite\" ",
    "lite": "lite-server",
    "postinstall": "typings install",
    "tsc": "tsc",
    "tsc:w": "tsc -w",
    "typings": "typings"
  },
  "license": "ISC",
  "dependencies": {
    "@angular/common""2.0.0-rc.1",
    "@angular/compiler""2.0.0-rc.1",
    "@angular/core""2.0.0-rc.1",
    "@angular/http""2.0.0-rc.1",
    "@angular/platform-browser""2.0.0-rc.1",
    "@angular/platform-browser-dynamic""2.0.0-rc.1",
    "@angular/router""2.0.0-rc.1",
    "@angular/router-deprecated""2.0.0-rc.1",
    "@angular/upgrade""2.0.0-rc.1",
    "systemjs": "0.19.27",
    "es6-shim": "^0.35.0",
    "reflect-metadata": "^0.1.3",
    "rxjs": "5.0.0-beta.6",
    "zone.js": "^0.6.12",
    "angular2-in-memory-web-api": "0.0.7",
    "bootstrap": "^3.3.6"
  },
  "devDependencies": {
    "concurrently": "^2.0.0",
    "lite-server": "^2.2.0",
    "typescript": "^1.8.10",
    "typings":"^0.8.1"
  }
}

tsconfig.json
{
  "compilerOptions": {
    "target": "es5",
    "module": "commonjs",
    "moduleResolution": "node",
    "sourceMap": true,
    "emitDecoratorMetadata": true,
    "experimentalDecorators": true,
    "removeComments": false,
    "noImplicitAny": false
  },
  "exclude": [
    "node_modules",
    "typings/main",
    "typings/main.d.ts"
  ]
}

tsconfig.json
{
  "ambientDependencies": {
    "es6-shim": "registry:dt/es6-shim#0.31.2+20160317120654",
    "jasmine": "registry:dt/jasmine#2.2.0+20160412134438",
    "node": "registry:dt/node#4.0.0+20160509154515"
  }
}

systemjs.config.js
 (function (global) {
    // map tells the System loader where to look for things
    var map = {
        'app': 'app', // 'dist',
        'rxjs': 'node_modules/rxjs',
        'angular2-in-memory-web-api': 'node_modules/angular2-in-memory-web-api',
        '@angular': 'node_modules/@angular'
    };
    // packages tells the System loader how to load when no filename and/or no extension
    var packages = {
        'app': { main: 'main.js', defaultExtension: 'js' },
        'rxjs': { defaultExtension: 'js' },
        'angular2-in-memory-web-api': { defaultExtension: 'js' },
    };
    var packageNames = [
      '@angular/common',
      '@angular/compiler',
      '@angular/core',
      '@angular/http',
      '@angular/platform-browser',
      '@angular/platform-browser-dynamic',
      '@angular/router',
      '@angular/router-deprecated',
      '@angular/testing',
      '@angular/upgrade',
    ];
    // add package entries for angular packages in the form '@angular/common': { main: 'index.js', defaultExtension: 'js' }
    packageNames.forEach(function (pkgName) {
        packages[pkgName] = { main: 'index.js', defaultExtension: 'js' };
    });
    var config = {
        map: map,
        packages: packages
    }
    System.config(config);
})(this);


三、執行指令

下戴angular2 的指令,自動會下戴packet.json的相依套件
npm install

啟動angular2
npm start

一切就這麼簡單…  從零開始…

四、Angular2的其他設定

如果大家有個Happy Start就繼續往下GO,如何才能完成Aangular2 的簡易版quick-start,先建立app資料夾,並加入以下檔案

app.component.ts
import { Component } from '@angular/core';
import { HeroDetailComponent } from './hero-detail.component';

@Component({
    selector: 'my-app',
    template: '<h1>My First Angular 2 App {{hero}}</h1><my-hero-detail></my-hero-detail>',
    directives: [HeroDetailComponent]
})
export class AppComponent {
    hero = 'Windstorm';
}

在這次的案例中,我就用多組件的案例呈現,angular2傾向於組件為主,所以允許部份組件可以重複使用,延用之前的語法{{}},用來呈現變數內容,其他相關的設定如下說明:

import component: import { HeroDetailComponent } from './hero-detail.component';
引用其他的組件名稱為HeroDetailComponent】,來自hero-detail.component.ts 的畫面範本

directives      : [HeroDetailComponent]
使用組件名稱【HeroDetailComponent】,到時就能在範本中使用此組件的selector name
  
hero-detail.component.ts 
import { Component, Input } from '@angular/core';
@Component({
    selector: 'my-hero-detail',
    template: `<table class="table">
    <tr>
        <th>hero system</th>
     </tr>
    <tr *ngFor = "let hero of heroes" >
    <td>{{hero}}</td>
    </tr>
    </table>`
})
export class HeroDetailComponent {
    heroes=["超人","x man","ice man","gad","spider man"]
}


*ngFor:延用angular1的廻圈語法,只是語法有些微不同
template:  html範本想要折行比較可維護性,請用鍵盤的【~】的上面的` ` 引號括起來喔,一般的引號會出錯。

main.ts
import { bootstrap }    from '@angular/platform-browser-dynamic';
import { AppComponent } from './app.component';
bootstrap(AppComponent);

原本測試版的檔案是boot.ts,但後來改為main.ts,內容也有些微不同

畫面呈現

補充說明: 如果想將注入的資料抽離獨立函式,如同angular1.0servicefactory 的模式示範:

app.component.ts
import { Component } from '@angular/core';
import { HeroDetailComponent } from './hero-detail';
@Component({
    selector: 'my-app',
    template: '<h1>{{title}}</h1><h2>My Heroes</h2><hero-detail></hero-detail>',
    directives: [HeroDetailComponent]
})
export class AppComponent {
    title = 'Tour of Heroes';  
}
如同上面的範例,引用component 組件

hero.ts : 物件宣告的方式
export class Hero {
    id: number;
    name: string;
}
用來傳遞物件內容,前端也走物件導向… 所以酷吧!

hero-service.ts  服務
import { Injectable } from '@angular/core';
import { Hero } from './hero'
@Injectable()
export class HeroService {
    getHeroes() {
        var 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 Promise.resolve(HEROES);
    }     
}
Angular2.0service程序比較複雜,先要宣告import { Injectable } from '@angular/core';
宣告service的類別之前要呼叫@Injectable() 但還沒瞭解其用意…

眼尖的大家有發現 return Promise.resolve(HEROES); 到底是什麼東東? 查了不少文件原來是javascript的非同步的一種方式,不過這不是本議題範圍… 跳過

hero-detail.ts
import { Component, OnInit } from '@angular/core';
import { Hero } from './hero';
import { HeroService } from './hero-service';
@Component({
    selector: '<hero-detail>',
    template: '<ul><li *ngFor ="let hero of heroes" ><span>{{hero.id}}</span> {{hero.name}}</li></ul>',
    providers: [HeroService]   //注入服務
})
export class HeroDetailComponent implements OnInit {
    title = 'Tour of Heroes';
    heroes = [];
    constructor(private heroService: HeroService) { }
    getHeroes() {
        this.heroService.getHeroes().then(heroesaa => this.heroes = heroesaa); // 呼叫service的函式
    }
    ngOnInit() {
        this.getHeroes();  // 呼叫getHeroes函式
    }
}

重頭戲…就在這裡囉… 前面那麼辛苦的建立servicehero物件,就是在這裡要用上了…
import { Component, OnInit } from '@angular/core'; //加入OnInit 初始化時執行的函式
import { Hero } from './hero';                    //匯入Hero的物件類別
import { HeroService } from './hero-service';    //匯入服務的類別名稱

providers: [HeroService]: 注入heroService服務

感謝大家… 有耐心的看完喔~  

2016年5月9日 星期一

C#的dll檔如何讓Foxpro 呼叫


    相信許多人維護舊有的系統,不得不牽就目前的系統環境,例如foxpro 已經維運了半世記了,無法相容於c#的技術,但c#保留其彈性,讓它可以被宣告成dll檔直接被foxpro直接呼叫,讓舊有的系統也能使用c#的功能,這是多酷的事情。

步驟一: 設定Visual Studio Tool 的環境

勾選 【讓組件成為COM-Visible(M)

勾選註冊COM Interop

步驟二: c# 的範例程式碼
namespace sample
{
    [ClassInterface(ClassInterfaceType.AutoDual)] //雖然不明白這行,但查詢文件都要加上此行
    [ProgId("sample.bt")]  //sample (專案的名稱) . bt(類別名稱
    public class bt
    {
        public string search_bt()
        {
            return "this is XXXXX search_bt";
        }
        public string search_bt2(string fl)
        {
            return fl;
        }
        public string search_bt3()
        {
            return "the new function";
        }
    }
}

步驟三:foxpro的範例程式

步驟四: 註冊c#dll元件

到指定Framework的目錄下,用regasm 路徑/檔名.dll


執行結果:

2016年3月1日 星期二

Android 首部曲-Customer ListView

Android 的開發者果然是佔大多數,至今java語言仍是排前三大,雖然PhoneGap 是一個不錯的開發工具,但是你想設計更複雜的介面,還是只能寫原生的Android APP的語言『JAVA,以下就介紹最常見的範例ListView

一、瞭解Layout
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="com.example.test.MainActivity" >

    <ListView
        android:layout_width="match_parent"  
        android:layout_height="match_parent"
        android:id="@+id/list_view"       />
    <Button      
     android:layout_height="wrap_content"
     android:layout_width="match_parent"
     android:text="@string/self_destruct"
     android:onClick="selfDestruct"
     android:layout_alignParentBottom="true"
     android:layout_alignParentRight="true"   
       />   
</RelativeLayout>

每份Android文件中都有一份layout.xml是主畫面的設計畫面,你可以在這文件中加上任何的控件等等,也包括listview button 等等,以下常見的參數
 android:layout_width : 控件的寬度,
match_parent:佔滿整個版面
fill_parent: 佔滿整個版面
wrap_content:依你的內容物大小決定,例如文字型的按鈕,會依照文字行列決定控件的大小
android:layout_height: 控件的高度,參數同上
android:id="@+id/list_view"  : 控件的id名稱 ,它的id名稱為list_view  

二、建立客製化的ListView

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_width="fill_parent"
     android:layout_height="fill_parent"
     android:orientation="horizontal" >
     <ImageView
           android:id="@+id/icon"
           android:layout_width="50dp"
           android:layout_height="50dp"
           android:layout_marginBottom="5dp"
           android:layout_marginLeft="5dp"
           android:layout_marginRight="5dp"
           android:layout_marginTop="5dp"
           android:src="@drawable/ic_launcher" />
     <TextView
           android:id="@+id/Itemname"
           android:layout_width="wrap_content"
           android:layout_height="wrap_content"
           android:textSize="20sp"
           android:paddingTop="5dp"/>
</LinearLayout>

為何已經有主版面的Layout為何就需要另外新增Layout?  因為想要客製化自己style 風格的ListView所以就需要另外新增,內容和主版面很像,這樣版中使用LinearLayout 就代表會像線性一樣放置控制,參數如下說明

android:orientation="horizontal" :  以水平的方式,放置控件,由左到右的方向
android:id="@+id/Itemname"  :這是設定id的名稱 @+id JAVA 就可以透過 r.id.Itemname 取得該物件,Itemname是你自訂的名稱,你可以改任何的名稱

以上的範本中,依序順序擺放位置,圖片會在文字的左邊,其他參數應該猜得到意思吧其中圖片的屬性android:src="@drawable/ic_launcher"  作者百思不得其解,原來Android目錄中res有五個都是以開頭為drawable命名的目錄,是擺放不同解析度的圖片喔,所以ic_launcher 就是圖片名稱啦~

三、建立客製化的ListView的類別
Pen.java :  //用來傳遞變數的物件
public class pen {
     public String  name
     public pen(String name)
    {
        this. name = name;      
    }
}

myAdapter.java
package com.example.test;
import java.util.ArrayList;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.TextView;
public class myAdapter extends ArrayAdapter<pen> {
// 建立arrayList<object> 將資料帶進來,用來產生listivew 的資料
      public myAdapter(Context context, ArrayList<pen> pens) {
            super(context, 0, pens);
         }
      @Override
         public View getView(int position, View convertView, ViewGroup parent) {
            pen penObj = getItem(position);       // 取得pen 物件,
            if (convertView == null) {
//透過r.layout.listview 語法,取得在res/layout/listview.xml
               convertView = LayoutInflater.from(getContext()).inflate(R.layout.listview, parent, false);
            }
//透過r.id.ItemName 語法,取得在res/layout/listview.xml  id為【ItemName】的控件
            TextView itemName = (TextView) convertView.findViewById(R.id.Itemname);         
            itemName.setText(penObj.name); //填入文字      
            return convertView;
        }
}

為何有R 這個物件,原來是Android提供方便工具,我們在res在之前的listviewLayout中已經設定@id的名稱,所以透過r.id.XXX就可以取得該物件,當然也可以透過r.layout.名稱取得res/layout/ layout範本,這點是不熟Android開發方法的朋友們,需要注意的喔!!!

四、在主頁面的Activity 呼叫客製化的ListView

public class MainActivity extends Activity {
    private ListView listView;   
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        ArrayList<pen> pens = new ArrayList<pen>();
        pens.add(new pen("鉛筆"));
        pens.add(new pen("原子筆"));
        pens.add(new pen("鋼筆"));
        pens.add(new pen("毛筆"));
        pens.add(new pen("鉛筆"));
       //建立pen 的物件集合,傳遞給自訂的listview
        myAdapter customerAdapter = new myAdapter(this,pens);       
//在主畫面的layout 取得listiview 控件
        listView=(ListView)findViewById(R.id.list_view);
//換成自訂的listiview範本
        listView.setAdapter(customerAdapter);     
    }
}

總結以上第一次的Android開發心得…   雖然不難但是有許多的參數要去查詢,Androiddeveloper 的文件非常的詳細,只要多多善加利用,你我也都是Android的開發者