2020年3月12日 星期四

angular - 版更9以後無法順利 npm publish --Trying to publish a package that has been compiled by Ivy. This is not allowed

簡介

最近因為將專案更新到 Angular 9.0.5 版本,原先所開發的模組 (library) 也一併更新。
但不知道為何專案更新版本之後,build 出來的模組都沒辦法正常發佈到 npm server
情形如下:
執行

    npm publish 

出現錯誤並且無法順利發佈
ERROR: Trying to publish a package that has been compiled by Ivy. This is not allowed.
Please delete and rebuild the package, without compiling with Ivy, before attempting to publish.


看起來是 npm 禁止發佈 ivy 編譯的模組。
至於是什麼原因,我目前不太清楚。
所以在編譯 library 時候必須禁用 ivy 或加上 --prod
而我不想禁用 ivy 編譯,所以我選擇以下加上 --prod 的編譯方式。


原本

    ng build mylib

改成

    ng build mylib --prod


如此再進行 npm publish 就可以正常發佈了。


2020年3月9日 星期一

option 事件偵聽在IE無效- option enent not work on IE

😀😁😂

簡介

解決 option 事件在 IE 無法正常執行。
因為平常很少將 select 做成用選單式的單選項目。
最近才遇到這個問題,發現在 IE 裡面, <option> 選單的 onclick 事件無法正常執行。
此時只要把 onlcick 事件移到 <select> 標籤即可。
原本在 option 的 onclick 事件。

    <select size="5" >
        <option value="" onclick="alert('123456')">12346</option>
    </select>

換成以下

    <select size="5" onclick="alert('123456')">
        <option value="">12346</option>
    </select>

2020年3月8日 星期日

angular-使用 proxy 解決跨域請求問題

簡介

因為 angular 專案使用 nodeJS 建立開發環境,
不論將來是否打算將開發後的檔案與後端程式合併,
都會遇到瀏覽器阻擋跨域請求的問題。
當然方法之一是寫後端程式開放 Access-Control-Allow-Origin
另一個方法則是用 proxy 方式,讓 nodejs 幫您的 angular 代理 http request,
以避免跨域被擋的問題發生。
瀏覽器發送跨域請求(cross-site request)相關文章可以參考以下這兩篇 MDN 的文章

伺服器端存取控制(CORS)

跨來源資源共用(CORS)

1.更改 package.json

更改 package.json 檔案 "script" 結構下的 "start"

    start": "ng serve --proxy-config proxy.config.json",

2.新增 proxy.config.json

  1. 在專案資料夾底下新增 proxy.config.json 檔案。
  2. http://127.0.0.1:2020 為自己本基架設的 API Server(後端)
  3. http://localhost:4200 為 angular 專案預設 port (前端)
  4. 以下設定表示 angular 程式只要向 http://localhost:4200/apiServer 發送 http request,會經 nodejs 向http://127.0.0.1:2020 發送 request
  5. 如此便能解決瀏覽器阻擋的跨域請求問題

    {
         "/apiServer/*": { 
          "target": "http://127.0.0.1:2020",
          "secure": false,
          "changeOrigin": true,
          "pathRewrite": {
            "^/apiServer": ""
          }
        },
    }

3.啟動方式

請注意如果要使用 proxy,啟動方式就不再是 ng serve ,而要用 npm start 取代。

  npm start

4.HTTP Reauest

以下為發送請求範例片段程式。
如下所示,向自家 server http://127.0.0.1:4200/apiServer/apitest2 請求, nodejs 伺服器會代為發 proxy 向 http://127.0.0.1:2020/apitest2 做 http request

    ngOnInit(){
        let headers = new HttpHeaders({
          "Content-Type":"application/json",
        });
        this.http.post('apiServer/apitest2',{headers: headers}).subscribe(
          (val) => {
            debugger
          },
          response => {},
          () => {});
      }

5.範例程式下載

範例程式 : proxy
尚未準備完成,之後補上 XD

2020年3月7日 星期六

angular多語系-ngx-translate

簡介

本篇將說明如何為您的 Angular 專案添加多語系檔案。
我們將使用 ngx-translate

ngx-translater概述

以下是官方網站說明:
NGX-Translate是Angular的國際化庫。它使您可以為內容定義不同語言的翻譯,並在它們之間輕鬆切換。
它使您可以訪問服務,指令和管道以處理任何動態或靜態內容。
NGX-Translate也非常模塊化。它的編寫方式可以非常輕鬆地用自定義實現替換任何部分,以防現有的部分不符合您的需求。

官方網站 : NGX-Translate
guthub : NGX-Translate GitHub

1.安裝多語系模組 ngx-translate

@ngx-translate/core -- 為該庫主要部分。

  npm install @ngx-translate/core --save

@ngx-translate/http-loader -- ngx-translate的加載程序,可讓您使用http加載翻譯檔案:.json。

  npm install @ngx-translate/http-loader --save

2.設定 app.module.ts


  import { BrowserModule } from '@angular/platform-browser';
  import { NgModule } from '@angular/core';

  import { AppRoutingModule } from './app-routing.module';
  import { AppComponent } from './app.component';

  import {HttpClientModule, HttpClient} from '@angular/common/http';
  import {TranslateModule, TranslateLoader} from '@ngx-translate/core';
  import {TranslateHttpLoader} from '@ngx-translate/http-loader';

  import {LanguageNamePipe} from './pipe';


  let i18nurl= '/assets/i18n/';
  export function HttpLoaderFactory(http: HttpClient) {
    return new TranslateHttpLoader(http, i18nurl, ".json");
  }


  @NgModule({
    declarations: [
      AppComponent,
      LanguageNamePipe,
    ],
    imports: [
      BrowserModule,
      AppRoutingModule,
      HttpClientModule,
      TranslateModule.forRoot({
        loader: {
          provide: TranslateLoader,
          useFactory: HttpLoaderFactory,
          deps: [HttpClient]
        }
      })
    ],
    providers: [],
    bootstrap: [AppComponent]
  })
  export class AppModule { }


3.設定 app.component.html

在 app.component.html 設定一個語言選擇器。
   
  <label style="width:100%;text-align: right;margin-top:25px;padding-right:30px;" >
    {{ 'HOME.SELECT' | translate }}  
    <select class="form-control" #langSelect (change)="translate.use(langSelect.value);changeLanguage(langSelect.value)" style="width:110px;"> 
    <option *ngFor="let lang of translate.getLangs()" [value]="lang" [selected]="lang === translate.currentLang">{{ lang | language_name}}</option>
      </select>
  </label>
  

4.增加一個 pipe

我們發現上述步驟 3. 需要一個 pipe 來過濾 select 選單的 en/jp/zh-tw 選項 (option選項),
所以需要增加一個 pipe 。
如下方程式碼,再將 pipe 加入到 app.module.ts 即可。 上方步驟 2.設定 app.module.ts 的程式已包含加入 LanguageNamePipe 的程式。

  import { Pipe, PipeTransform } from '@angular/core';

  @Pipe({
      name: 'language_name',
  })
  
  export class LanguageNamePipe implements PipeTransform {
      transform(str: any): any {
          var cname='';
          switch(str){
              case("en"):
                  cname="English";
              break;
              case("zh-tw"):
                  cname="正體中文";
              break;
              case("jp"):
                  cname="日本語";
              break;
              case(""):
                  cname="";
              break;
          }
          return cname;
      }
  }
  

5.設定 app.component.ts

在 app.component.ts 設定載入語言檔案。
app.component.ts

  import { Component } from '@angular/core';
  import {TranslateService} from '@ngx-translate/core';
  
  @Component({
    selector: 'app-root',
    templateUrl: './app.component.html',
    styleUrls: ['./app.component.scss']
  })
  export class AppComponent {
    title = 'language';
    constructor(public translate: TranslateService) {
      var lang = localStorage.getItem('language');//取得預設語言
  
      if(lang==null ||  lang==""){
        lang =navigator.language.toLowerCase() ;//判斷瀏覽器語言 en/jp/zh-tw,並轉為小寫
      }
      translate.addLangs(["en", "zh-tw","jp"]); //加入語系列表。目前此專案有三個語系
      translate.setDefaultLang(lang);// 設定預設語言
      translate.use(lang);//載入預設語言
    }
  
    /**
     * 在選擇語言的時候設定 localStorage
     * @param language : en/jp/zh-tw
     */
    changeLanguage(language:string){
      localStorage.setItem('language', language);
    }
  
  }
  

6.其他 component 用法

可以在 component 的 html 頁面直接使用即可,ts 不須加入任何程式。
如下範例:

  {{ 'HOME.SELECT' | translate }} 

7.線上範例

2020年3月4日 星期三

angular-快速版本更新

簡介

有時候專案版本更新,如果跨太多版本號,
可能會有一些莫名的問題無法成功更新專案。
而且有些錯誤訊息看不懂到底錯在哪
這時使用以下方更快。
不過以下方式是否比較快則不一定適用每個人
至少我自己這樣更新是比較快的XD。

1.更新 CLI 工具

如果電腦裡面沒有其他專案,就直接更新 CLI 工具吧。
CLI 工具更新,可在 cmd 下輸入以下
請注意,如果電腦裡還有其他專案,則不建議直接更新 CLI 工具。

    npm install -g @angular-devkit/schematics-cli

2.建立一個新專案

先 new 一個專案。
請注意,如果沒有執行 1 ,在 new 完專案後,應該執行 ng update,
並根據建議更新指令(如下方所示) 逐一執行。確保得到一個官方最新版本專案。

    Name                      Version                  Command to update
    --------------------------------------------------------------------------------
    @angular/cli              8.3.5 -> 8.3.6           ng update @angular/cli
    @angular/core             8.2.7 -> 8.2.8           ng update @angular/core
    rxjs                      6.4.0 -> 6.5.3           ng update rxjs

3.將舊專案資料搬移到新專案--模組

將所有src/app裡面的資料夾模組先丟到新專案裡,執行 ng serve 跑跑看
不包含以下
  1. app.component.html
  2. app.component.scss
  3. app.component.spec.ts
  4. app.component.ts
  5. app.module.ts
  6. app-routing.module.ts
如果有問題可以先執行 npm audit fix 或根據出現的訊息修正檔案。

4.將舊專案 plugin 照著讓新專案安裝

如果OK的話,依照舊專案裡的 package.json 安裝(npm install) 各 plugin 元件的最新版本。
再試著跑 ng serve

4.將舊專案 plugin 照著讓新專案安裝

再把除了 package.json,package-lock.json 的檔案都複製過去覆蓋。
大致為以下檔案
  1. app.component.html
  2. app.component.scss
  3. app.component.spec.ts
  4. app.component.ts
  5. app.module.ts
  6. app-routing.module.ts

5.修復與開啟

繼續試著跑 ng serve,再看情形執行 npm audit fix 。

6.完成

通常這樣之後如果有錯誤,提示資訊就比較容易看懂哪裡有問題了。
我通常最後沒辦法時候就都這種方式更新都能成功。

2020年3月3日 星期二

angular-支援 IE 10, IE11

支援版本 : IE11, IE10
只要更新專案資料夾裡的
tsconfig.json 檔案即可

    "compilerOptions"  ---> "target": "es2015",

改為

    "compilerOptions"  ---> "target": "es5",


============================== 原始碼如下 ==============================
tsconfig.json

    {
        "compileOnSave": false,      
        "compilerOptions": {
          ..
          "target": "es2015",
          ..
        },
        ..
    }

改為

    {
        "compileOnSave": false,
        "compilerOptions": {
          ..
          "target": "es5",
          ..
        },
        ..
    }
    

2020年3月2日 星期一

將 angular 專案變成 android app (使用cordova) -- 工具安裝設定篇

預設環境: Windows10 !!請注意,目前只有 APK 版
影片連結
openJDK 為 GPL license 為比較需要注意的事項。如要採用請詳加考慮喔。
我個人比較推薦影片使用的 openJDK,因為文章中的 openJDK 編譯的時候會有 https 下載問題
也就是它的 JDK 裡面似乎沒有 https license 的樣子
build apk 的時候會要下載 gradle 。那時候會失敗。也就是文章介紹的 openJDK 我沒成功安裝過。
會用以上圖片是因為我之前安裝 java ,後來換掉了,
但是我發現下載後的 gradle 暫存檔會存在 C:\Users\orange-cat\.gradle 資料夾裡 ,
但是後來我把 C:\Users\orange-cat\.gradle 資料夾整個刪掉要重 build 的時候就失敗了
是後來換了 Zulu OpenJDK 才成功的。所以建議可以下載 Zulu OpenJDK
如果之前安裝過 java ,要換 openJDK 記得換掉 JDK 後也要把 C:\Users\orange-cat\.gradle 全部刪掉再重新 build apk
官方網址 https://www.azul.com/downloads/zulu-community/?package=jdk

1.安裝 Open JDK

step1. 可到官網 JDK8 下載 openJDK
step2. 下載版本號 8
step3. 下載openJDK
step4. 下載openJDK完後解壓縮,資料夾內容如下
step5. 複製取代
在 C:\Program Files 底下建立 Java\jdk1.8.0_221,
並將下載來的openJDK內容複製到 C:\Program Files\Java\jdk1.8.0_221裡
!! 請注意 ,資料夾可任意名稱與任何位置,只是此範例安裝在 C:\Program Files\Java\jdk1.8.0_221 。
差別在之後的 JAVA_HOME 路徑設定。

2.安裝 Android Studio

可到官網下載 Android Studio

3.下載相關的 Android API

step1. 到剛剛下載 Android Studio 的資料夾,開啟應用程式
step2.在右上方選單捩點選 [SDK Manager] 圖示
step3. 點選 Create Virtual Device...
step4. 隨便選一個虛擬裝置
step5. 選一個喜歡的Android API ,最好不要太新也不要太舊
step6. 挑選放置 API tool 位置
這時候系統會讓你挑選放置 API tool 的位置,通常不能跟安裝的資料夾相同
可以隨便選擇預設,或如此範例選在 C:\android sdk 裡
step7. 加入 gradle
新安裝的 Android Studio 如果沒有 gradle 會無法 build apk 檔案
可到這裡下載 Gradle
step8. 範例直接下載 Binary-only 即可
step9. 解壓縮完直接丟入安裝資料夾 C:\Program Files\Android\Android Studio 即可。如圖

4.安裝 NodeJS

如果要開發 angular 專案是必須的。 可到官網下載 nodejs

5.安裝 Cordova

執行以下安裝

    npm install -g cordova
    

6.設定使用者變數,系統變數

step1. 隨意開啟一個資料夾,對著左邊欄位的 [本機] 選項按右鍵出現選單,
選擇最後一個選項 [內容(R)]。
step2. 在新出現的選單後,選擇 [進階系統設定] 。
step3. 在出現的 [系統內容] 選單裡,選擇 [進階] ,點選 [環境變數(N)] 。
step4. 在上方 [使用者變數(U)] 添加以下變數 :
圖中(1)ANDROID_SDK_ROOT C:\android sdk
圖中(2)JAVA_HOME C:\Program Files\Java\jdk1.8.0_221
圖中(5)
C:\android sdk\platform-tools
C:\android sdk\build-tools
C:\android sdk\tools
添加完成記得按 [確定] 儲存設定。

以上設定完成。
環境設定完成後,可參考下一篇,如何建置專案。
將 angular 專案變成 android app (使用cordova) -- 專案建置篇