Angular
RxJS
JavaScript
使用 RxJS:range 完成信用卡有效日期選項
2022/03/04 14:31:06
0
1201
layout
要呈現的畫面如下圖,
切版內容如下:
HTML
<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
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
: 建立多少個數值的數列
簡易範例:
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~12 月份,並且我在個位數前面加個 0 ,使資料看起來有一致性。
- 年份:信用卡有效期限基本上在 3 到 5 年左右,所以也不會無限上綱。
想法是我今天只要訂出月份 1 到 12 月,並建立一個陣列把 1 到 12 月份去模板上跑迴圈,並且使用 click
事件把選到的值重新渲染在畫面上即可。然後我就可以這樣做:
程式碼不長也很簡單。
取得年份與月份
透過 range 建立年份與月份的陣列資料,並透過 click 事件把選到的值渲染在模板上,細節寫在註解中。
app.component.ts
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
方法。
<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