SlideShare a Scribd company logo
從零開始的 Angular
網頁應用程式
Taoyuan
Part II: Service & Routing & Form
Kun-Neng Hung 洪堃能
2025/04/22
課程時間軸
04/15 Part I 04/22 Part II 05/04 Workshop
主題:Angular
Angular框架介紹 Angular元件開發
開發環境建置
Gemini AI
記憶卡牌遊戲設計 記憶卡牌遊戲開發
主題:AI & 遊戲
Angular服務介紹
Angular路由介紹
Angular表單處理
成果發表
Gemini AI Gemini AI
● 服務與依賴注入
● 路由設計
● 表單處理與資料驗證
● 記憶卡牌遊戲設計
課程重點
Angular 服務與依賴注入
● 把 cards 放在元件並不是良好的設計
○ 難以共享給其他元件使用,因為必須在多個元件間傳遞
○ 未來這些資料可能很龐大,元件內部邏輯容易太過複雜
○ 需要有一個專門管理資料的地方,並提供操作方式給需要使用的元件
● 服務(service)除了能滿足上述需求,另一個重要功能就是利用它跟後端進
行溝通。因此,將這些功能由元件中抽離出來,能讓程式碼更簡潔、易維護。
重構現有架構
● 建立第一個服務(在名為 services 的資料夾中)
ng generate service services/cards
● 將元件中的共用資料與邏輯移至服務
● 將服務注入至元件以進行操作
服務開發實作
title = 'Memory Game';
get cards(): Card[] {
return this.cardsService.cards;
}
get moves(): number {
return this.cardsService.moves;
}
get isWin(): boolean {
return this.cardsService.isWin;
}
app.component.ts
constructor(private cardsService: CardsService) { }
ngOnInit() {
this.cardsService.startGame();
}
startGame() {
this.cardsService.startGame();
}
flipCard(id: number) {
this.cardsService.flipCard(id);
}
注入服務後的元件
由服務取得,並提供給範本的變數 值 來自範本的事件,交由服務處理
將服務注入至元件,即可獲得它提供的變數及方法
import { Injectable } from '@angular/core';
import { Card } from '../models/card';
@Injectable({
providedIn: 'root'
})
export class CardsService {
cards: Card[] = [];
// 略
startGame() {
// 略
}
// 略
}
cards.service.ts
@Injectable 裝飾子
注入層級:全域
服務做了什麼?
CardsService <app-root>
資料
<app-card>
。
。
。
依賴注入
取得
更新
取得
更新 <app-card>
處理
● Router
在 app.config.ts 將 provideRouter(routes) 加入至
providers 陣列後,以 @angular/router 匯入
● HttpClient
在 app.config.ts 將 provideHttpClient() 加入至
providers 陣列後,以 @angular/common/http 匯入
Angular 內建的服務
● 依賴注入是一個著名的設計模式,包含
○ 依賴:元件取得自身以外的資料或功能來使用
○ 注入:當元件需要這些功能時,注入器會去 registry 中找尋
並返回或建立一個實體,將它注入至元件
● 細節請參考依賴注入
延伸閱讀:依賴注入
Angular 路由設計
強化遊戲體驗
Start Game
主畫面 遊戲畫面
● 套用守衛(guard)根據訂製的規則來限制或允許路由導引
● 套用解析器(resolver)來處理或加工路由間傳遞的資料
● 在不同的路由共享共通範本(template)
使用路由的好處
● 建立兩個元件(在名為 components 的資料夾中)
ng generate component components/main
ng generate component components/playground
● 移動 app.component.ts 內部所有的參數與方法至
playground.component.ts (意即,遊戲畫面改呈現在 playground 元件)
● 在 app.routes.ts 加入路由
建立路由規則
import { Routes } from '@angular/router';
export const routes: Routes = [
{
path: '',
loadComponent: () => import('./components/main/main.component').then(m => m.MainComponent)
},
{
path: 'playground',
loadComponent: () => import('./components/playground/playground.component').then(m => m.PlaygroundComponent)
},
{
path: '**',
redirectTo: ''
}
];
app.routes.ts
若給定空路徑,則導引到 main 元件
若給定 playground 路徑,則導引到 playground 元件
給定任何路徑都會導到空路徑
注意:
1. 這些路徑規則有順序性(由上而下)
2. 萬用路徑的規則要放在最末位
● App 元件
○ 在 app.component.html 中加入 <router-outlet></router-outlet>
○ 在 app.component.ts 中匯入 RouterOutlet
● Main 元件
○ 在 main.component.html 中加入按鈕
○ 在 main.component.ts 中注入 Router 服務
○ 按鈕事件加入觸發路由導向this.router.navigate(['/playground']);
路由導向至元件
<router-outlet></router-outlet>
app.component.html
import { Component } from '@angular/core';
import { RouterOutlet } from '@angular/router';
@Component({
selector: 'app-root',
imports: [RouterOutlet],
templateUrl: './app.component.html',
styleUrl: './app.component.css'
})
export class AppComponent { }
app.component.ts
<button type="button" (click)="startGame()">Start Game</button>
main.component.html
import { Component } from '@angular/core';
import { Router } from '@angular/router';
@Component({ /** 略 */ })
export class MainComponent {
constructor(private router: Router) { }
startGame() {
this.router.navigate(['/playground']);
}
}
main.component.ts
確認啟用路由功能
import { ApplicationConfig } from '@angular/core';
import { provideRouter } from '@angular/router';
import { routes } from './app.routes';
export const appConfig: ApplicationConfig = {
providers: [
provideRouter(routes)
]
};
app.config.ts
表單處理與資料驗證
“表單就只是在輸入框填資料而已? ”
● 追蹤元件狀態
● 判斷哪些控制項是 valid 或 invalid
● 針對輸入內容,適當顯示錯誤訊息
表單可以協助
number
color
checkbox,radio
date
file
month
text
password
range
time
登入遊戲帳號
遊戲畫面
主畫面
Start Game
帳號
Log In
密碼
登入畫面
● 範本驅動表單 Template-driven forms
○ 匯入 FormsModule
● 響應式表單 Reactive forms
○ 匯入 ReactiveFormsModule
Angular 表單有兩種
1. 建立一個對 ngForm 指令的參考 myForm
2. 每個表單控制項都套有 ngModel 指令,做雙向綁定(two-way binding)
3. 該 ngForm (父)能與內部 ngModel (子)進行互動
範本驅動表單
<form #myForm="ngForm" (ngSubmit)="submit()">
<p>
<label>Account:</label>
<input type="text" [(ngModel)]="user.account" name="account" required />
</p>
<p>
<label>Password:</label>
<input type="password" [(ngModel)]="user.password" name="password" required />
</p>
<p>
<button type="submit" [disabled]="myForm.invalid">Submit</button>
</p>
</form>
以 NgModel 做雙向綁定(表單 ↔模型)
.html
user = {
account: '',
password: ''
};
.ts
1. 以 formGroup 指令套用到整個表單,並綁定一個元件變數名稱 myForm
2. 由 FormControl 實體化每個控制項
3. 以程式撰寫元件類別層級(非範本)的控制項定義及驗證機制
響應式表單
<form [formGroup]="myForm" (ngSubmit)="submit()">
<p>
<label>Account:</label>
<input type="text" formControlName="account" />
</p>
<p>
<label>Password:</label>
<input type="password" formControlName="password" />
</p>
<p>
<button type="submit" [disabled]="myForm.invalid">Submit</button>
</p>
</form>
myForm = new FormGroup<LoginForm>({
account: new FormControl(''),
password: new FormControl('')
}
.html
.ts
表單驗證
class Validators {
static min(min: number): ValidatorFn;
static max(max: number): ValidatorFn;
static required(control: AbstractControl<any, any>): ValidationErrors | null;
static requiredTrue(control: AbstractControl<any, any>): ValidationErrors | null;
static email(control: AbstractControl<any, any>): ValidationErrors | null;
static minLength(minLength: number): ValidatorFn;
static maxLength(maxLength: number): ValidatorFn;
static pattern(pattern: string | RegExp): ValidatorFn;
static nullValidator(control: AbstractControl<any, any>): ValidationErrors | null;
static compose(validators: null): null;
static compose(validators: (ValidatorFn | null | undefined)[]): ValidatorFn | null;
static composeAsync(validators: (AsyncValidatorFn | null)[]): AsyncValidatorFn | null;
}
內建驗證器(built-in validator)
我們可以自訂驗證器,讓驗證器接受一個
控制元件實例並返回
● 驗證通過:null
● 驗證失敗:錯誤對映表
myForm = new FormGroup<LoginForm>({
account: new FormControl('', [
Validators.required,
Validators.minLength(4),
forbiddenNameValidator(/admin/i)
]),
password: new FormControl('', [
Validators.required,
Validators.minLength(6)
])
}
import { ValidatorFn, AbstractControl, ValidationErrors } from '@angular/forms';
export function forbiddenNameValidator(reg: RegExp): ValidatorFn {
return (control: AbstractControl): ValidationErrors | null => {
const isForbidden = reg.test(control.value);
return isForbidden ? { forbiddenName: { value: control.value }} : null;
}
}
<form #myForm="ngForm" (ngSubmit)="submit()">
<p>
<label>Account:</label>
<input type="text" [(ngModel)]="user.account" name="account"
required minlength="4" appForbiddenName="admin" #account="ngModel">
</p>
<p>
<label>Password:</label>
<input type="password" [(ngModel)]="user.password" name="password"
required minlength="6">
</p>
<p>
<button type="submit" [disabled]="myForm.invalid">Submit</button>
</p>
</form>
.html 範本驅動表單
user = {
account: '',
password: ''
};
.ts
表單驗證規則
表單驗證規則
響應式表單
.html
<form [formGroup]="myForm" (ngSubmit)="submit()">
<p>
<label>Account:</label>
<input type="text" formControlName="account" />
</p>
<p>
<label>Password:</label>
<input type="password" formControlName="password" />
</p>
<p>
<button type="submit" [disabled]="myForm.invalid">Submit</button>
</p>
</form>
.html
myForm = new FormGroup<LoginForm>({
account: new FormControl('', [
Validators.required,
Validators.minLength(4),
forbiddenNameValidator(/admin/i)
]),
password: new FormControl('', [
Validators.required,
Validators.minLength(6)
])
}
.ts
● 將範本成為表單驗證規則的來源,會變得難以閱讀和快速維護
● 當添加越來越多的驗證器標籤,表單的可讀性和可維護性會降低
● 表單驗證邏輯不能簡單地進行單元測試
範本驅動表單的缺點
● 範本變得簡潔許多,只要專注於實現表現層的邏輯
● 有助於實現更進階的使用案例,如根據後端資料來動態定義表單
響應式表單的優點
fetchFormFields(): Observable<FormField[]> {
// This can be replaced by actual HTTP API
return of([
{ name: 'username', type: 'text', label: 'User Name', required: true },
{ name: 'email', type: 'email', label: 'Email', required: true },
{ name: 'age', type: 'number', label: 'Age', required: false }
]);
}
響應式表單與內部控制項都提供 RxJs observable API 以進行資料操作
this.myForm.valueChanges.pipe(
filter((value) => !!value.account),
map((value) => value.account.toUpperCase()),
filter(() => this.myForm.valid)
).subscribe((value) => {
console.log(`Valid account: ${JSON.stringify(value)}`);
});
this.myForm.controls.password.valueChanges.pipe(
debounceTime(400),
distinctUntilChanged()
).subscribe(newValue => {
this.passwordStrength = newValue ? newValue.length : 0;
});
表單樣式
ng-touched
使用者曾經進入過
ng-untouched
使用者未曾進入過
ng-valid
滿足表單規則且通過驗證
ng-invalid
未滿足表單規則或未通過驗證
ng-pristine
使用者未曾改變過值
ng-dirty
使用者改變過值
<div *ngIf="account.invalid && (account.dirty || account.touched)" class="alert">
<ng-container *ngIf="account.errors?.['required']">
Account is required.
</ng-container>
<ng-container *ngIf="account.errors?.['minlength']">
Account must be at least 4 characters long.
</ng-container>
<ng-container *ngIf="account.errors?.['forbiddenName']">
Account cannot begin with admin.
</ng-container>
</div>
.ng-valid[required], .ng-valid.required {
border-left: 5px solid green;
}
.ng-invalid:not(form) {
border-left: 5px solid red;
}
.alert {
background-color: #fed3d3;
color: #820000;
padding: 0.5rem;
margin-bottom: 1rem;
}
● Angular 範本驅動表單
● Angular 響應式表單
● 表單樣式
● 進階應用
範例
demo & source code
● 建立一個元件(在名為 components 的資料夾中)
ng generate component components/login
● 在 login.component.ts 匯入 ReactiveFormsModule
● 添加 /login 路由
登入畫面之表單開發
{
path: 'login',
loadComponent: () => import('./components/login/login.component').then(m => m.LoginComponent)
}
<form [formGroup]="loginForm" (ngSubmit)="logIn()">
</form>
login.component.html
輸入
按鈕
錯誤資訊
login.component.html
<fieldset>
<legend>User Information</legend>
<label for="account">Account</label>
<input id="account" type="email" placeholder="Email"
autocomplete="username" formControlName="account" />
<label for="password">Password</label>
<input id="password" type="password" placeholder="Password"
autocomplete="current-password" formControlName="password" />
</fieldset>
輸入
<button type="submit">Log in</button> 按鈕
login.component.html
<ng-container *ngIf="isSubmitted && account.errors">
<ng-container *ngIf="account.errors['required']; else invalidEmail">
Account is required
</ng-container>
<ng-template #invalidEmail>
<ng-container *ngIf="account.invalid">
Invalid email address
</ng-container>
</ng-template>
</ng-container>
錯誤資訊
login.component.html
<ng-container *ngIf="isSubmitted && password.errors">
<ng-container *ngIf="password.errors['required']; else invalidPassword">
Password is required
</ng-container>
<ng-template #invalidPassword>
<ng-container *ngIf="password.invalid">
Invalid password length (>= {{ password.errors['minlength']?.requiredLength }})
</ng-container>
</ng-template>
</ng-container>
錯誤資訊
loginForm!: FormGroup;
get account() {
return this.loginForm.controls['account'];
}
get password() {
return this.loginForm.controls['password'];
}
isFormChanged: boolean = false;
isSubmitted: boolean = false;
constructor(private fb: FormBuilder, private router: Router) { }
login.component.ts
ngOnInit(): void {
this.loginForm = this.fb.group({
account: new FormControl<string>('', {
validators: [Validators.required, Validators.email]
}),
password: new FormControl<string>('', {
validators: [Validators.required, Validators.minLength(6)]
})
});
this.loginForm.valueChanges.subscribe(() => {
this.isFormChanged = true;
this.isSubmitted = false;
});
}
login.component.ts
ngOnInit 鉤子
logIn(): void {
this.isSubmitted = true;
if (this.password.errors?.['required']) {
this.isFormChanged = false;
}
if (this.loginForm.invalid) {
return;
}
this.router.navigate(['/playground']);
}
login.component.ts
滑鼠點擊事件
記憶卡牌遊戲開發
目前已完成
遊戲畫面
playground
主畫面
main
Start Game
帳號
Log In
密碼
登入畫面
login
遊戲畫面
playground
主畫面 main
Start Game
帳號
Sign Up
Log In
密碼
登入畫面 login
再加點...
帳號申請 signup
帳號
Apply
密碼
valid ?
Yes
No
遊戲畫面
playground
主畫面 main
Start Game
帳號
Sign Up
Log In
密碼
登入畫面 login
更完整些...
帳號申請 signup
帳號
Apply
密碼
後端
valid ?
Yes
No
● Angular 服務與依賴注入
● Angular 路由設計
● Angular 表單介紹
● 表單資料驗證
● 記憶卡牌遊戲開發
總結
source code

More Related Content

Similar to 20250422 從零開始的 Angular 網頁應用程式 Part II: Service & Routing & Form (20)

Core data lightweight_migration
Core data lightweight_migrationCore data lightweight_migration
Core data lightweight_migration
Michael Pan
 
前端MVC之backbone
前端MVC之backbone前端MVC之backbone
前端MVC之backbone
Jerry Xie
 
Angular Meetup 04 - Angular PWA 之沒有網路的日子 20190731
Angular Meetup 04 - Angular PWA 之沒有網路的日子 20190731Angular Meetup 04 - Angular PWA 之沒有網路的日子 20190731
Angular Meetup 04 - Angular PWA 之沒有網路的日子 20190731
升煌 黃
 
Struts1+ hibernate3
Struts1+ hibernate3Struts1+ hibernate3
Struts1+ hibernate3
edanwade
 
Angular 4 新手入門攻略完全制霸
Angular 4 新手入門攻略完全制霸Angular 4 新手入門攻略完全制霸
Angular 4 新手入門攻略完全制霸
Will Huang
 
全栈三个月开发绩效系统 using Rails 7.1 to develop people performance evaluation system
全栈三个月开发绩效系统 using Rails 7.1 to develop people performance evaluation system全栈三个月开发绩效系统 using Rails 7.1 to develop people performance evaluation system
全栈三个月开发绩效系统 using Rails 7.1 to develop people performance evaluation system
Eric Guo
 
Power flow簡介
Power flow簡介Power flow簡介
Power flow簡介
Sky Wu
 
以HTML5和COIMOTION打造跨平台App
以HTML5和COIMOTION打造跨平台App以HTML5和COIMOTION打造跨平台App
以HTML5和COIMOTION打造跨平台App
Ben Lue
 
javascript的分层概念 --- 阿当
javascript的分层概念 --- 阿当javascript的分层概念 --- 阿当
javascript的分层概念 --- 阿当
裕波 周
 
2015 年逢甲大學資訊系:ASP.NET MVC 4 教育訓練5
2015 年逢甲大學資訊系:ASP.NET MVC 4 教育訓練52015 年逢甲大學資訊系:ASP.NET MVC 4 教育訓練5
2015 年逢甲大學資訊系:ASP.NET MVC 4 教育訓練5
Duran Hsieh
 
旺铺前端设计和实现
旺铺前端设计和实现旺铺前端设计和实现
旺铺前端设计和实现
hua qiu
 
YUI ─ 阿大
YUI ─ 阿大YUI ─ 阿大
YUI ─ 阿大
taobao.com
 
Arduino Yún使用Http restful api控制io
Arduino Yún使用Http restful api控制ioArduino Yún使用Http restful api控制io
Arduino Yún使用Http restful api控制io
吳錫修 (ShyiShiou Wu)
 
Flutter Forward Extended in Google Developer Taipei
Flutter Forward Extended in Google Developer TaipeiFlutter Forward Extended in Google Developer Taipei
Flutter Forward Extended in Google Developer Taipei
abc873693
 
Windows Mobile Widget 開發
Windows Mobile Widget 開發Windows Mobile Widget 開發
Windows Mobile Widget 開發
Chui-Wen Chiu
 
行動商務實務 - PhoneGap Advance
行動商務實務 - PhoneGap Advance行動商務實務 - PhoneGap Advance
行動商務實務 - PhoneGap Advance
My own sweet home!
 
ModernWeb 2017 angular component
ModernWeb 2017 angular componentModernWeb 2017 angular component
ModernWeb 2017 angular component
Chieh Kai Yang
 
使用者認證
使用者認證使用者認證
使用者認證
Shengyou Fan
 
與 Sign in with Apple 的愛恨情仇 @ iPlayground2020
與 Sign in with Apple 的愛恨情仇 @ iPlayground2020與 Sign in with Apple 的愛恨情仇 @ iPlayground2020
與 Sign in with Apple 的愛恨情仇 @ iPlayground2020
Johnny Sung
 
Core data lightweight_migration
Core data lightweight_migrationCore data lightweight_migration
Core data lightweight_migration
Michael Pan
 
前端MVC之backbone
前端MVC之backbone前端MVC之backbone
前端MVC之backbone
Jerry Xie
 
Angular Meetup 04 - Angular PWA 之沒有網路的日子 20190731
Angular Meetup 04 - Angular PWA 之沒有網路的日子 20190731Angular Meetup 04 - Angular PWA 之沒有網路的日子 20190731
Angular Meetup 04 - Angular PWA 之沒有網路的日子 20190731
升煌 黃
 
Struts1+ hibernate3
Struts1+ hibernate3Struts1+ hibernate3
Struts1+ hibernate3
edanwade
 
Angular 4 新手入門攻略完全制霸
Angular 4 新手入門攻略完全制霸Angular 4 新手入門攻略完全制霸
Angular 4 新手入門攻略完全制霸
Will Huang
 
全栈三个月开发绩效系统 using Rails 7.1 to develop people performance evaluation system
全栈三个月开发绩效系统 using Rails 7.1 to develop people performance evaluation system全栈三个月开发绩效系统 using Rails 7.1 to develop people performance evaluation system
全栈三个月开发绩效系统 using Rails 7.1 to develop people performance evaluation system
Eric Guo
 
Power flow簡介
Power flow簡介Power flow簡介
Power flow簡介
Sky Wu
 
以HTML5和COIMOTION打造跨平台App
以HTML5和COIMOTION打造跨平台App以HTML5和COIMOTION打造跨平台App
以HTML5和COIMOTION打造跨平台App
Ben Lue
 
javascript的分层概念 --- 阿当
javascript的分层概念 --- 阿当javascript的分层概念 --- 阿当
javascript的分层概念 --- 阿当
裕波 周
 
2015 年逢甲大學資訊系:ASP.NET MVC 4 教育訓練5
2015 年逢甲大學資訊系:ASP.NET MVC 4 教育訓練52015 年逢甲大學資訊系:ASP.NET MVC 4 教育訓練5
2015 年逢甲大學資訊系:ASP.NET MVC 4 教育訓練5
Duran Hsieh
 
旺铺前端设计和实现
旺铺前端设计和实现旺铺前端设计和实现
旺铺前端设计和实现
hua qiu
 
YUI ─ 阿大
YUI ─ 阿大YUI ─ 阿大
YUI ─ 阿大
taobao.com
 
Arduino Yún使用Http restful api控制io
Arduino Yún使用Http restful api控制ioArduino Yún使用Http restful api控制io
Arduino Yún使用Http restful api控制io
吳錫修 (ShyiShiou Wu)
 
Flutter Forward Extended in Google Developer Taipei
Flutter Forward Extended in Google Developer TaipeiFlutter Forward Extended in Google Developer Taipei
Flutter Forward Extended in Google Developer Taipei
abc873693
 
Windows Mobile Widget 開發
Windows Mobile Widget 開發Windows Mobile Widget 開發
Windows Mobile Widget 開發
Chui-Wen Chiu
 
行動商務實務 - PhoneGap Advance
行動商務實務 - PhoneGap Advance行動商務實務 - PhoneGap Advance
行動商務實務 - PhoneGap Advance
My own sweet home!
 
ModernWeb 2017 angular component
ModernWeb 2017 angular componentModernWeb 2017 angular component
ModernWeb 2017 angular component
Chieh Kai Yang
 
與 Sign in with Apple 的愛恨情仇 @ iPlayground2020
與 Sign in with Apple 的愛恨情仇 @ iPlayground2020與 Sign in with Apple 的愛恨情仇 @ iPlayground2020
與 Sign in with Apple 的愛恨情仇 @ iPlayground2020
Johnny Sung
 

More from Kun-Neng Hung (6)

20250322 Build with AI - 以 MediaPipe 建構裝置端 LLM
20250322 Build with AI - 以 MediaPipe 建構裝置端 LLM20250322 Build with AI - 以 MediaPipe 建構裝置端 LLM
20250322 Build with AI - 以 MediaPipe 建構裝置端 LLM
Kun-Neng Hung
 
20250322 Build with AI - 使用 Vertex AI 建構 LLM 應用
20250322 Build with AI - 使用 Vertex AI 建構 LLM 應用20250322 Build with AI - 使用 Vertex AI 建構 LLM 應用
20250322 Build with AI - 使用 Vertex AI 建構 LLM 應用
Kun-Neng Hung
 
20241117 自製網頁遊戲之輔助 AI 應用實例:使用 Google Gemini AI 提升玩家決策
20241117 自製網頁遊戲之輔助 AI 應用實例:使用 Google Gemini AI 提升玩家決策20241117 自製網頁遊戲之輔助 AI 應用實例:使用 Google Gemini AI 提升玩家決策
20241117 自製網頁遊戲之輔助 AI 應用實例:使用 Google Gemini AI 提升玩家決策
Kun-Neng Hung
 
20240518 將 Google Gemini 整合至 Angular 成為互動式 AI 應用程式
20240518 將 Google Gemini 整合至 Angular 成為互動式 AI 應用程式20240518 將 Google Gemini 整合至 Angular 成為互動式 AI 應用程式
20240518 將 Google Gemini 整合至 Angular 成為互動式 AI 應用程式
Kun-Neng Hung
 
20221119 DevFest 2022 - 初探 Angular 響應式表單
20221119 DevFest 2022 - 初探 Angular 響應式表單20221119 DevFest 2022 - 初探 Angular 響應式表單
20221119 DevFest 2022 - 初探 Angular 響應式表單
Kun-Neng Hung
 
20210411 全端網頁開發起手式:建構並佈署Angular網頁應用程式至GCP
20210411 全端網頁開發起手式:建構並佈署Angular網頁應用程式至GCP20210411 全端網頁開發起手式:建構並佈署Angular網頁應用程式至GCP
20210411 全端網頁開發起手式:建構並佈署Angular網頁應用程式至GCP
Kun-Neng Hung
 
20250322 Build with AI - 以 MediaPipe 建構裝置端 LLM
20250322 Build with AI - 以 MediaPipe 建構裝置端 LLM20250322 Build with AI - 以 MediaPipe 建構裝置端 LLM
20250322 Build with AI - 以 MediaPipe 建構裝置端 LLM
Kun-Neng Hung
 
20250322 Build with AI - 使用 Vertex AI 建構 LLM 應用
20250322 Build with AI - 使用 Vertex AI 建構 LLM 應用20250322 Build with AI - 使用 Vertex AI 建構 LLM 應用
20250322 Build with AI - 使用 Vertex AI 建構 LLM 應用
Kun-Neng Hung
 
20241117 自製網頁遊戲之輔助 AI 應用實例:使用 Google Gemini AI 提升玩家決策
20241117 自製網頁遊戲之輔助 AI 應用實例:使用 Google Gemini AI 提升玩家決策20241117 自製網頁遊戲之輔助 AI 應用實例:使用 Google Gemini AI 提升玩家決策
20241117 自製網頁遊戲之輔助 AI 應用實例:使用 Google Gemini AI 提升玩家決策
Kun-Neng Hung
 
20240518 將 Google Gemini 整合至 Angular 成為互動式 AI 應用程式
20240518 將 Google Gemini 整合至 Angular 成為互動式 AI 應用程式20240518 將 Google Gemini 整合至 Angular 成為互動式 AI 應用程式
20240518 將 Google Gemini 整合至 Angular 成為互動式 AI 應用程式
Kun-Neng Hung
 
20221119 DevFest 2022 - 初探 Angular 響應式表單
20221119 DevFest 2022 - 初探 Angular 響應式表單20221119 DevFest 2022 - 初探 Angular 響應式表單
20221119 DevFest 2022 - 初探 Angular 響應式表單
Kun-Neng Hung
 
20210411 全端網頁開發起手式:建構並佈署Angular網頁應用程式至GCP
20210411 全端網頁開發起手式:建構並佈署Angular網頁應用程式至GCP20210411 全端網頁開發起手式:建構並佈署Angular網頁應用程式至GCP
20210411 全端網頁開發起手式:建構並佈署Angular網頁應用程式至GCP
Kun-Neng Hung
 

20250422 從零開始的 Angular 網頁應用程式 Part II: Service & Routing & Form