2021年9月17日 星期五

b-table 實作選擇機制

html
<b-table borderless="true" head-variant="dark" fixed sticky-header striped hover :items="銷貨單明細" :fields="欄位s" :filter="filter" selectable select-mode="single" ref="table銷貨單明細" v-on:row-selected="onRowSelected">
<template #cell(已選擇)="data">
{{data.rowSelected?'&#10146;':''}} // 標示選擇列
</template>
</b-table> 

javascript
data() {
        return {
選擇位置: null,
已選擇明細s: [],
欄位s: [
{
key: '已選擇',
label: '',
thStyle: { width: '1em' },
tdClass: 'text-center',
},            
...
computed: {
        已選擇明細() {
            for (let a of this.銷貨單明細) {
                if (a.項次 == this.已選擇明細s[0].項次) {
                    return a;
                }
            }            
        },
...
methods: {
        onRowSelected(items) {
            this.已選擇明細s = items;
            if (items.length > 0) this.選擇位置 = this.銷貨單明細.indexOf(this.已選擇明細);
            else if (this.選擇位置 != null) this.選擇明細();
        },
        選擇明細() {
            let $vue = this;
            if (!$vue.$refs.table銷貨單明細.isRowSelected($vue.選擇位置))
                setTimeout(function () {
                    $vue.$refs.table銷貨單明細.selectRow($vue.選擇位置);
                    $vue.選擇明細();
                }, 100);
        },
...
watch: {
       銷貨單明細() {
            if (this.銷貨單明細.length > 0) {
                if (this.選擇位置!=null) this.選擇明細();
            }
        },
...

※透過onRowSelected得到的物件必須視為唯讀,和實際物件不是同一個記憶體位置,而是複製出來的,不可直接判斷物件是否相等,若要修改則先找出對應的物件再修改,可透過computed回傳對應物件

利用 javascript 複製物件

產生新物件(深層複製)
JSON.parse(JSON.stringify(xxx))

覆蓋屬性值(淺層複製)
Object.assign(target,source)

2021年9月16日 星期四

BootstrapVue 學習心得

驗證 form 元素範例
<BFormInput :id="input-name" placeholder="請選擇" v-model="name" :state="!name? false:null"></BFormInput>
<BFormInvalidFeedback :id="input-name-feedback">請輸入姓名</BFormInvalidFeedback>


下拉選單分群
選項資料用 label 搭配 options 餵給 b-form-select,label 就是群組名稱
ex.
後端
活動s.Where(a => a.時間 >= DateTime.Today.FirstDayOfMonth()).OrderBy(a => a.時間).ToList().GroupBy(a=>a.時間.FirstDayOfMonth()).Select(a=>new { label=a.Key.ToString("yyyy/M"), 
options=a.Select(b => new { value = b.id, text = b.content }).ToList() })
前端
<b-form-select v-model="活動" :options="活動s"></b-form-select>


讓 bootstrapvue toast 顯示 html or 替換內容
javascript
錯誤訊息.value = 錯誤訊息.replaceAll('\n', '<br>');
顯示錯誤訊息視窗.value = true;

html
<Teleport to="body">
    <div class="toast-container position-fixed top-0 end-0">
        <BToast v-model="顯示錯誤訊息視窗" variant="danger" title="發生錯誤" auto-hide="false">              <div v-html='錯誤訊息'></div>
        </BToast>
    </div>
</Teleport>

2021年9月13日 星期一

b-table 學習心得

※table 綁定的 items 和原始陣列不同,是透過複製得到,因此修改 items 不會連動修改原始陣列

事件函數不支援中文,除非加上(),但這樣就無法取得預設參數
ex: v-on:row-clicked="選擇資料"

垂直置中

.table td, .table th {
        vertical-align: middle;
}
內距縮小 : 加入 small 屬性

若內含按鈕會呼叫後端,搭配 b-spinner 會造成目前捲軸位置跑掉

解法1 : 記憶捲軸位置
解法2 : 呼叫後端不要顯示 b-spinner (其他情況呼叫後端才顯示 b-spinner)
※ 可能是 webform 才會有此問題
※ 後來發現使用 b-pagination 分頁時,change 事件會在未換頁時一樣觸發(例如新增或刪除資料),若於換頁時自動設定捲軸置頂,就會被干擾,必須另外用變數記錄頁數比對是否真的有換頁

垂直捲軸置頂(通常用在查詢後)

$('#b-table').parent().scrollTop(0);

加入 primary-key 屬性可以改善效能(尚須確認)

<b-table primary-key="xxx" 

過濾文字機制不要直接綁定屬性,改用 watch 延遲設定,避免資料較多(超過100筆)時輸入文字卡卡

<b-input v-model="filtertext" placeholder="過濾..."></b-input> 
<b-table :filter="filter"
 watch: {
                filtertext(newVal, oldVal) {
                    clearTimeout(this.$_timeout);
                    this.$_timeout = setTimeout(() => {
                        this.filter = newVal
                    }, 500); // set this value to your preferred debounce timeout
                }
            },

欄位為單一核取方塊的置中效果

<style scoped>
    .form-check {
        padding-left: 0.5em;
    }
    :deep(.form-check) .form-check-input {
        margin-left: unset;
        float:unset;
    }   
</style>

window.innerHeight vs $(window).height()

原則上兩個回傳的值一樣,但
1. $(xxx).height() 不會考慮開啟開發人員工具的情況
2. 若用在透過 $(xxx).height() 設定容器高度,某些用法會有不同結果,window.innerHeight 的結果才是正確的

結論: 一律使用 window.innerHeight 取得視窗高度

input 連結 datalist 用程式控制彈出選項

範例: nextTick(() => document.querySelector('input').showPicker());  ※僅支援現代瀏覽器