0%

Angualr 筆記 - 使用 RxJS:range 完成信用卡有效日期選項

延續 CSS 筆記 - 使用 ul li 製作互動式下拉選單來延伸做一個信用卡的有效期限選單,本次專案使用 Angular 框架開發,故功能會使用 Angular 的方式記錄。

layout

要呈現的畫面如下圖,

credit card valid date

切版內容大致與延續的文章相同,以下就不贅述。

HTML

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
<label>信用卡有效期限:</label>
<div class="creditCard">
<div class="drop">
<div class="dropOption">
<span>有效月份</span>
</div>

<ul class="dropdown">
<li>選項 1</li>
<li>選項 2</li>
<li>選項 3</li>
<li>選項 4</li>
<li>選項 5</li>
<li>選項 6</li>
<li>選項 7</li>
<li>選項 8</li>
</ul>
</div>
<span>/</span>

<div class="drop">
<div class="dropOption">
<span>有效年份 </span>
</div>

<ul class="dropdown">
<li>選項 1</li>
<li>選項 2</li>
<li>選項 3</li>
<li>選項 4</li>
<li>選項 5</li>
<li>選項 6</li>
<li>選項 7</li>
<li>選項 8</li>
</ul>
</div>
</div>

SCSS

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
label {
font-size: 24px;
padding: 0.5rem;
font-weight: bold;
color: #333;
border-left: orange 5px solid;
margin-bottom: 0;
}
.creditCard {
display: flex;
align-items: center;
padding-top: 1rem;
> span {
margin: 0 1rem;
}
.drop {
position: relative;
display: block;
width: 130px;
// margin: 0 0 10px;
&:hover {
.dropOption {
display: block;
}
}
&:hover {
.dropdown {
display: block;
}
}
&:hover {
.dropdown.close {
display: none;
}
}
.dropOption {
position: relative;
width: auto;
color: #666;
font-size: 20px;
background-color: #fff;
padding: 10px;
border: 1px solid #888;
border-radius: 5px;
box-sizing: border-box;
cursor: pointer;
&::after {
content: "";
position: absolute;
top: 20px;
right: 12px;
border-width: 8px 6px;
border-style: solid;
border-color: #999 transparent transparent transparent;
}
}
.dropdown {
display: none;
width: 100%;
max-height: 350px;
position: absolute;
color: #333;
padding: 0;
margin: 0;
background-color: #f9f9f9;
box-shadow: 0px 2px 3px 0px #ccc;
border-radius: 6px;
box-sizing: border-box;
overflow: auto;
z-index: 10;
> li {
display: block;
color: #000;
padding: 12px;
font-size: 20px;
margin: 0 10px;
cursor: pointer;
&:first-child {
margin: 10px;
}
&:last-child {
margin-bottom: 10px;
}
&:hover {
background-color: #eee;
border-radius: 6px;
}
}
&::-webkit-scrollbar {
width: 15px;
}
&::-webkit-scrollbar-track {
background-color: #eee;
border-radius: 6px;
}
&::-webkit-scrollbar-thumb {
background-color: #888;
border-radius: 15px;
}
&::-webkit-scrollbar-button {
background-color: #f9f9f9;
}
}
}
}

使用 RxJS: range 來完成功能

range 顧名思義就是依照一個範圍內的數列資料建立 Observable,包含兩個參數:
start: 從哪個數值開始
count: 建立多少個數值的數列

簡易範例:

1
2
3
4
5
6
7
import { range } from "rxjs";

range(3, 4).subscribe((data) => console.log(`range 範例: ${data}`));
// range 範例: 3
// range 範例: 4
// range 範例: 5
// range 範例: 6

tip: range 參數只能放 number。

透過以上範例我可以自訂一個數列的範圍,那月份跟年份就有解了,因為都有範圍:

  1. 月份:1~12 月份,並且我在個位數前面加個 0 ,使資料看起來有一致性。
  2. 年份:信用卡有效期限基本上在 3 到 5 年左右,所以也不會無限上綱。

想法是我今天只要訂出月份 1 到 12 月,並且建立一個陣列把 1 到 12 月份去模板上跑迴圈,並且使用 click 事件把選到的值重新渲染在畫面上即可。然後我就可以這樣做:

程式碼不長也很簡單。

取得年份與月份

透過 range 建立年份與月份的陣列資料,並透過 click 事件把選到的值渲染在模板上,細節寫在註解中。
app.component.ts

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
ngOnInit(): void {
this.validMonth(); //務必呼叫方法,才能跑出陣列資料
}

//*有效月份
creditMonth: string[] = [];
monthValue: string;

validMonth() {
range(1, 12)
.pipe(
map((x) => {
return ('0' + x.toString()).slice(-2);
//因為我只要取最後兩位數,所以要先轉成字串再去處理
})
)
.subscribe((res) => {
this.creditMonth.push(res); //將每一月份依序放到陣列中
});
}

checkMonth(month: string) {
this.monthValue = month; //選到的月份顯示於下拉選單主選擇框內
}

app.component.html
修改模板語法,加上 ngFor 指令以及 click 方法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<label>信用卡有效期限:</label>
<div class="creditCard">
<div class="drop">
<div class="dropOption">
<span>{{ monthValue ? monthValue : "有效月份" }}</span>
</div>

<ul class="dropdown">
<ng-container *ngFor="let item of creditMonth">
<li (click)="checkMonth(item)">{{ item }}</li>
</ng-container>
</ul>
</div>
<span>/</span>

<div class="drop">
<div class="dropOption">
<span>{{ yearValue ? yearValue : "有效年份" }} </span>
</div>

<ul class="dropdown">
<ng-container *ngFor="let item of creditYear">
<li (click)="checkYear(item)">{{ item }}</li>
</ng-container>
</ul>
</div>
</div>

小結

善用 RxJS 的 range 事件可以建立有範圍的資料,這次的應用就覺得很有意思,不僅好管理也提升效率,非常推薦喔!

DEMO

連結:https://stackblitz.com/edit/angular-ivy-ppxopm?embed=1&file=src/app/app.component.ts

參考資料