IT이야기

Vue - 부트스트랩 테이블 사용자 지정 구성 요소의 데이터 업데이트

cyworld 2022. 3. 24. 22:10
반응형

Vue - 부트스트랩 테이블 사용자 지정 구성 요소의 데이터 업데이트

Bootstrap Vue 라이브러리의 기존 기능을 확장하는 사용자 지정 구성 요소를 Vue 2.0에서 만들려고 함<b-table>. 인덱스.jsp에 정의된 removeRow 및 resetData 기능이 원하는 방식으로 작동하지 않는다는 점을 제외하면 대부분 원하는 방식으로 작동한다.

RemoveRow는 행을 시각적으로 제거하고, 행에서 행을 제거한다.data받침대. 그러나 행은 다음 상호작용 후에 다시 나타난다(그림, 필터 등).그래서 그것은 사실 올바른 것을 업데이트하는 것이 아니다.v-model을 항목들의 얕은 복사본으로 사용하려고 하는데, 원래 데이터 세트에 영향을 주지 않고 삭제하려고 하는데, 그냥 뭔가 놓치고 있어.

resetData는 테이블의 데이터를 다시 올바르게 설정하지만, 별도의 상호 작용(정렬, 필터 등)을 수행할 때까지 다시 추가된 행을 볼 수 없도록 테이블을 다시 렌더링하지 않으며, 이 경우 다시 나타난다.

그래서 나는 내가 어느 정도 가까운 사이라는 것을 알지만, 어떻게 하면 이 요소를 올바르게 작동시킬 수 있는지, 그리고 내가 이 구성 요소의 어떤 부분도 개선할 수 있는지에 대한 통찰력을 정말 고마워할 것이다.

오릴리테이블vuejs

const OreillyTable =  {
inheritAttrs: false,
data: function () {
    return {
        filter: null,
        sortDesc: false,
        hideEmpty: false,
        isBusy: false,
        currentPage: 1,
        data: null
    }
},
mounted: function () {
    let filtered = this.slots.filter(function(value, index, arr){
        return value.customRender;
    });
    this.slots = filtered;
},
methods: {
    oreillyTableSort (a, b, key) {
        if (a[key] === null || b[key] === null) {
            return a[key] === null && b[key] !== null ? -1 : (a[key] !== null && b[key] === null ? 1 : 0);
        } else if (typeof a[key] === 'number' && typeof b[key] === 'number') {
            // If both compared fields are native numbers
            return a[key] < b[key] ? -1 : (a[key] > b[key] ? 1 : 0)
        } else {
            // Stringify the field data and use String.localeCompare
            return this.toString(a[key]).localeCompare(this.toString(b[key]), undefined, {
                numeric: true
            });
        }
    },

    toString (val) {
        return typeof val !== "undefined" && val != null ? val.toString() : '';
    },

    oreillyFilter (filteredItems) {
        this.totalRows = filteredItems.length;
        this.currentPage = 1;
    }
},
props: {
    fields: {
        type: Array
    },
    items: {
        type: Array,
        required: true
    },
    hideEmpty: {
        type: Boolean
    },
    filterPlaceholder: {
        type: String,
        default: "Filter"
    },
    sortFunction: {
        type: Function,
        default: null
    },
    filterFunction: {
        type: Function,
        default: null
    },
    slots: {
        type: Array
    },
    sortBy: {
        type: String,
        default: null
    },
    perPage: {
        type: Number,
        default: 10
    },
    value: {

    }
},
template: `<div :class="{ 'no-events' : isBusy }">
            <b-row>
                <b-col md="12">
                    <b-form-group class="mb-2 col-md-3 float-right pr-0">
                        <b-input-group>
                            <b-form-input v-model="filter" :placeholder="filterPlaceholder" class="form-control" />
                        </b-input-group>
                    </b-form-group>
                </b-col>
            </b-row>
            <div class="position-relative">
                <div v-if="isBusy" class="loader"></div>
                <b-table stacked="md" outlined responsive striped hover
                    v-bind="$attrs"
                    v-model="data"
                    :show-empty="!hideEmpty"
                    :items="items"
                    :fields="fields"
                    :no-provider-sorting="true" 
                    :no-sort-reset="true"
                    :filter="filter"
                    :sort-by.sync="sortBy" 
                    :sort-desc.sync="sortDesc" 
                    :sort-compare="sortFunction === null ? this.oreillyTableSort : sortFunction" 
                    :busy.sync="isBusy"
                    :current-page="currentPage"
                    :per-page="perPage"
                    @filtered="filterFunction === null ? this.oreillyFilter : filterFunction">

                    <template :slot="slot.key" slot-scope="row" v-for="slot in slots">
                        <slot :name="slot.key" :data="row"></slot>
                    </template>
                </b-table>

                <b-row v-if="items.length > perPage">
                    <b-col sm="12">
                        <b-pagination size="md" :total-rows="items.length" v-model="currentPage" :per-page="perPage"></b-pagination>
                    </b-col>
                </b-row>
            </div>
        </div>`
};

인덱스.jsp

<script>
Vue.use(window.vuelidate.default);

Vue.component('oreilly-table', OreillyTable);

const dashboardItems = [
    { id: 12, firstName: "John", lastName: "Adams", tmNumber: "588999", team: "Corporate", flapjackCount: 4, enrollDate: "2018-11-05" },
    { id: 13, firstName: "George", lastName: "Washington", tmNumber: "422111", team: "America", flapjackCount: 28, enrollDate: "2018-10-01" },
    { id: 14, firstName: "Abraham", lastName: "Lincoln", tmNumber: "358789", team: "America", flapjackCount: 16, enrollDate: "2017-09-02" },
    { id: 15, firstName: "Jimmy", lastName: "Carter", tmNumber: "225763", team: "Core", flapjackCount: 9, enrollDate: "2018-03-02" },
    { id: 16, firstName: "Thomas", lastName: "Jefferson", tmNumber: "169796", team: "Core", flapjackCount: 14, enrollDate: "2018-05-01" }
];

const Dashboard = {
    template: `<jsp:include page="dashboard.jsp"/>`,
    data: function(){
        return {            
            notification: {
                text: "The Great Flapjack Contest will be held on December 25, 2018.",
                variant: "primary",
                timer: true
            },
            fields: [
                { key: "name", label: "Name", sortable: true, customRender: true },
                { key: "team", label: "Team", sortable: true },
                { key: "enrollDate", label: "Enrollment Date", sortable: true, formatter: (value) => {return new Date(value).toLocaleDateString();} },
                { key: "flapjackCount", sortable: true },
                { key: "id", label: "", 'class': 'text-center', customRender: true }
            ]
        }
    },
    methods: {
        removeRow: function(id) {
            this.$refs.table.isBusy = true;
            setTimeout(() => { console.log("Ajax Request Here"); this.$refs.table.isBusy = false; }, 1000);
            const index = this.$refs.table.data.findIndex(item => item.id === id) 
            if (~index) 
                this.$refs.table.data.splice(index, 1)  
        },
        resetData: function() {
            this.$refs.table.data = dashboardItems;
        }
    }
};

const router = new VueRouter({
    mode: 'history',
    base: "/ProjectTemplate/flapjack",
    routes: [
        { path: '/enroll', component: Enroll },
        { path: '/', component: Dashboard },
        { path: '/404', component: NotFound },  
        { path: '*', redirect: '/404' }
    ]
});

new Vue({router}).$mount('#app');

대시보드.jsp

<compress:html>
<div>
    <oreilly-table ref="table" :items="dashboardItems" :slots="fields" :fields="fields">
        <template slot="name" slot-scope="row">
            {{ row.data.item.firstName }} {{ row.data.item.lastName }} ({{ row.data.item.tmNumber }})
        </template>
        <template slot="id" slot-scope="row">
            <a href="#" @click.prevent="removeRow(row.data.item.id)">Remove</a>
        </template>
    </oreilly-table>
    <footer class="footer position-sticky fixed-bottom bg-light">
        <div class="container text-center">
            <router-link tag="button" class="btn btn-outline-secondary" id="button" to="/enroll">Enroll</router-link>
            &emsp;
            <b-button @click.prevent="resetData" size="md" variant="outline-danger">Reset</b-button>
        </div>
    </footer>
</div>

나는 간단한 예로 당신의 문제를 재현하려고 노력했다. (https://codesandbox.io/s/m30wqm0xk8?module=%2Fsrc%2Fcomponents%2FGridTest.vue) 참조) 그리고 나는 당신이 가지고 있는 것과 같은 문제를 발견했다.다른 사람들이 이미 말했듯이, 나는 원본 데이터를 재설정하는 가장 쉬운 방법이 복사본을 만드는 것이라는 것에 동의한다.나는 데이터를 제거하고 재설정하는 두 가지 방법을 썼다.

methods: {
    removeRow(id) {
      const index = this.records.findIndex(item => item.index === id);

      this.records.splice(index, 1);
    },
    resetData() {
      this.records = this.copyOfOrigin.slice(0);
    }
  }

탑재에서 나는 데이터의 복사본을 만드는 기능을 실행한다.그렇지 않으면 원래 어레이에 대한 참조만 만들기 때문에 슬라이스로 이 작업을 수행한다(일반적으로 JS는 값별로 전달되지만 vue 설명서에 나와 있는 대로 개체와 함께 참조되어 내부적으로 vue에 전달됨(Vue 문서 참조: Vue 문서 참조).

mounted: function() {
    this.copyOfOrigin = this.records.slice(0);
  } 

이제 간단히 레코드를 제거할 수 있을 뿐 아니라 모든 데이터를 재설정할 수도 있다.

전체 데모 참조

나는 이것이 너의 문제를 해결해주길 바라며, 질문이 있다면 언제든지 물어봐.

참조URL: https://stackoverflow.com/questions/53525360/vue-update-data-on-bootstrap-table-custom-component

반응형