Skip to content

Commit

Permalink
Merge pull request #10 from muhimasri/support-v-model
Browse files Browse the repository at this point in the history
Support v model
  • Loading branch information
muhimasri authored Oct 4, 2021
2 parents 1b309da + b0136ed commit d85f5d0
Show file tree
Hide file tree
Showing 7 changed files with 256 additions and 196 deletions.
87 changes: 47 additions & 40 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@




# BootstrapVue Editable Table
![Demo](https://github.com/muhimasri/b-editable-table/blob/main/images/demo.gif)

Expand Down Expand Up @@ -89,7 +90,53 @@ For `select` element, the options can be passed as another property (as shown in
{ value: 'b', text: 'Third Option' }
]
```
## Data Binding:
|Data | Binding |
|--|--|
| :items="items" | One-way binding
| v-model="items" | Two-way binding

When using `v-model` the data will be updated directly as follows:

`<b-editable-table v-model="items" :fields="fields"></b-editable-table>`

Otherwise, using `:items` prop to pass data will require updating it manually on input change as follows:
```javascript
<template>
<b-editable-table :items="items" :fields="fields" @input-change="handleInput"></b-editable-table>
</template>

<script>
import BEditableTable from 'bootstrap-vue-editable-table';
export default {
components: {
BEditableTable
},
data() {
return {
fields: [
{ key: "name", label: "Name", type: "text", editable: true, placeholder: "Enter Name..."},
{ key: "department", label: "Department", type: "select", options: ['Marketing', 'Development', 'HR', 'Accounting'], editable: true },
{ key: "age", label: "Age", type:"range", min:"0", max:"100", editable: true, placeholder: "Enter Age..." },
{ key: "dateOfBirth", label: "Date Of Birth", size:"lg", locale:"fr", type: "date", editable: true },
{ key: "isActive", label: "Is Active", type: "checkbox", editable: true },
],
items: [
{ age: 40, name: 'Dickerson', department: 'Development', dateOfBirth: '1984-05-20', isActive: true },
{ age: 21, name: 'Larsen', department: 'Marketing', dateOfBirth: '1984-05-20', isActive: false },
{ age: 89, name: 'Geneva', department: 'HR', dateOfBirth: '1984-05-20', isActive: false },
{ age: 38, name: 'Jami', department: 'Accounting', dateOfBirth: '1984-05-20', isActive: true }
]
};
},
methods: {
handleInput(value, data) {
this.items[data.index][data.field.key] = value;
}
}
};
</script>
```
## Form Elements:
Every column requires a `type` and `editable` property in order to make the cell editable:

Expand Down Expand Up @@ -183,51 +230,11 @@ export default {
```
`.data-cell` is an internal class used for the `span` element within every non-editable cell. You can customize it however you like.

## Data Binding:
Editable cells use `v-model` internally to support **two-way data bindings**. Any change will reflect directly on the `items` array.

## Events:
|Event |Arguments | Description |
|--|--|--|
| input-change &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; |`value` - Current cell value <br/> `data` - Row data (the same object returned by Bootstrap)| Emitted when any cell input changes

**Example:**
```javascript
<template>
<b-editable-table :items="items" :fields="fields" @input-change="handleInput"></b-editable-table>
</template>

<script>
import BEditableTable from 'bootstrap-vue-editable-table';
export default {
components: {
BEditableTable
},
data() {
return {
fields: [
{ key: "name", label: "Name", type: "text", editable: true},
{ key: "department", label: "Department", type: "select", options: ['Marketing', 'Development', 'HR', 'Accounting'], editable: true },
{ key: "age", label: "Age", type: "number", editable: true },
{ key: "dateOfBirth", label: "Date Of Birth", type: "date", editable: true },
{ key: "isActive", label: "Is Active", type: "checkbox", editable: true },
],
items: [
{ age: 40, name: 'Dickerson', department: 'Development', dateOfBirth: '1984-05-20', isActive: true },
{ age: 21, name: 'Larsen', department: 'Marketing', dateOfBirth: '1984-05-20', isActive: false },
{ age: 89, name: 'Geneva', department: 'HR', dateOfBirth: '1984-05-20', isActive: false },
{ age: 38, name: 'Jami', department: 'Accounting', dateOfBirth: '1984-05-20', isActive: true }
]
};
},
methods: {
handleInput(value, data) {
// Handle input change
}
}
};
</script>
```
## Custom Cell
To customize a none editable cell, you can use scoped slots to customize a particular field.

Expand Down
5 changes: 3 additions & 2 deletions dev/examples/basic-example.vue
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<template>
<div>
<b-editable-table bordered :small="true" fixed class="editable-table" :items="items" :fields="fields" @input-change="handleInput"></b-editable-table>
<b-editable-table bordered :small="true" fixed class="editable-table" v-model="items" :fields="fields" @input-change="handleInput"></b-editable-table>
<pre>
{{items}}
</pre>
Expand Down Expand Up @@ -32,7 +32,8 @@ export default {
},
methods: {
handleInput(value, data) {
console.log(data)
console.log(data);
// this.items[data.index][data.field.key] = value;
}
}
};
Expand Down
119 changes: 56 additions & 63 deletions dist/b-editable-table.esm.js
Original file line number Diff line number Diff line change
Expand Up @@ -11928,7 +11928,8 @@ var script = Vue.extend({
},
props: {
fields: Array,
items: Array
items: Array,
value: Array
},
directives: {
focus: {
Expand Down Expand Up @@ -11969,18 +11970,20 @@ var script = Vue.extend({
type: String,
default: null
},
selectedRow: {
type: Object,
default: null
}
tableItems: this.value ? this.value.map(item => ({ ...item,
isEdit: false
})) : this.items.map(item => ({ ...item,
isEdit: false
}))
};
},

methods: {
handleEditCell(e, index, name) {
e.stopPropagation();
this.mapItems();
this.tableItems[index].isEdit = true;
this.selectedCell = name;
this.selectedRow = index;
},

handleKeydown(e, index, data) {
Expand All @@ -12001,17 +12004,30 @@ var script = Vue.extend({

fieldIndex = i;
this.selectedCell = this.fields[fieldIndex].key;
this.selectedRow = rowIndex;
this.mapItems();
this.tableItems[rowIndex].isEdit = true;
} else if (e.code === "Escape") {
e.preventDefault();
this.selectedCell = null;
this.selectedRow = null;
this.mapItems();
}
},

handleClickOut() {
this.selectedCell = null;
this.selectedRow = null;
this.mapItems();
},

inputHandler(value, data, key) {
this.tableItems[data.index][key] = value;
this.$emit('input-change', value, data);
this.$emit('input', this.tableItems);
},

mapItems() {
this.tableItems = this.tableItems.map(item => ({ ...item,
isEdit: false
}));
}

}
Expand Down Expand Up @@ -12163,11 +12179,14 @@ var __vue_render__ = function () {
value: _vm.handleClickOut,
expression: "handleClickOut"
}],
attrs: {
"items": _vm.tableItems
},
scopedSlots: _vm._u([_vm._l(_vm.fields, function (field, index) {
return {
key: "cell(" + field.key + ")",
fn: function (data) {
return [field.type === 'date' && _vm.selectedRow === data.index && _vm.selectedCell === field.key && field.editable ? _c('b-form-datepicker', _vm._b({
return [field.type === 'date' && _vm.tableItems[data.index].isEdit && _vm.selectedCell === field.key && field.editable ? _c('b-form-datepicker', _vm._b({
directives: [{
name: "focus",
rawName: "v-focus",
Expand All @@ -12176,120 +12195,94 @@ var __vue_render__ = function () {
}],
key: index,
attrs: {
"type": field.type
"type": field.type,
"value": _vm.tableItems[data.index][field.key]
},
on: {
"input": function ($event) {
return _vm.$emit('input-change', $event, data);
"input": function (value) {
return _vm.inputHandler(value, data, field.key);
}
},
nativeOn: {
"keydown": function ($event) {
return _vm.handleKeydown($event, index, data);
}
},
model: {
value: _vm.items[data.index][field.key],
callback: function ($$v) {
_vm.$set(_vm.items[data.index], field.key, $$v);
},
expression: "items[data.index][field.key]"
}
}, 'b-form-datepicker', Object.assign({}, field), false)) : field.type === 'select' && _vm.selectedRow === data.index && _vm.selectedCell === field.key && field.editable ? _c('b-form-select', _vm._b({
}, 'b-form-datepicker', Object.assign({}, field), false)) : field.type === 'select' && _vm.tableItems[data.index].isEdit && _vm.selectedCell === field.key && field.editable ? _c('b-form-select', _vm._b({
directives: [{
name: "focus",
rawName: "v-focus"
}],
key: index,
attrs: {
"value": _vm.tableItems[data.index][field.key]
},
on: {
"change": function ($event) {
return _vm.$emit('input-change', $event, data);
"change": function (value) {
return _vm.inputHandler(value, data, field.key);
}
},
nativeOn: {
"keydown": function ($event) {
return _vm.handleKeydown($event, index, data);
}
},
model: {
value: _vm.items[data.index][field.key],
callback: function ($$v) {
_vm.$set(_vm.items[data.index], field.key, $$v);
},
expression: "items[data.index][field.key]"
}
}, 'b-form-select', Object.assign({}, field), false)) : field.type === 'checkbox' && _vm.selectedRow === data.index && _vm.selectedCell === field.key && field.editable ? _c('b-form-checkbox', _vm._b({
}, 'b-form-select', Object.assign({}, field), false)) : field.type === 'checkbox' && _vm.tableItems[data.index].isEdit && _vm.selectedCell === field.key && field.editable ? _c('b-form-checkbox', _vm._b({
directives: [{
name: "focus",
rawName: "v-focus",
value: 'checkbox',
expression: "'checkbox'"
}],
key: index,
attrs: {
"checked": _vm.tableItems[data.index][field.key]
},
on: {
"change": function ($event) {
return _vm.$emit('input-change', $event, data);
"change": function (value) {
return _vm.inputHandler(value, data, field.key);
}
},
nativeOn: {
"keydown": function ($event) {
return _vm.handleKeydown($event, index, data);
}
},
model: {
value: _vm.items[data.index][field.key],
callback: function ($$v) {
_vm.$set(_vm.items[data.index], field.key, $$v);
},
expression: "items[data.index][field.key]"
}
}, 'b-form-checkbox', Object.assign({}, field), false)) : field.type === 'rating' && field.type && _vm.selectedRow === data.index && _vm.selectedCell === field.key && field.editable ? _c('b-form-rating', _vm._b({
}, 'b-form-checkbox', Object.assign({}, field), false)) : field.type === 'rating' && field.type && _vm.tableItems[data.index].isEdit && _vm.selectedCell === field.key && field.editable ? _c('b-form-rating', _vm._b({
directives: [{
name: "focus",
rawName: "v-focus"
}],
key: index,
attrs: {
"type": field.type
"type": field.type,
"value": _vm.tableItems[data.index][field.key]
},
on: {
"keydown": function ($event) {
return _vm.handleKeydown($event, index, data);
},
"change": function ($event) {
return _vm.$emit('input-change', $event, data);
"change": function (value) {
return _vm.inputHandler(value, data, field.key);
}
},
model: {
value: _vm.items[data.index][field.key],
callback: function ($$v) {
_vm.$set(_vm.items[data.index], field.key, $$v);
},
expression: "items[data.index][field.key]"
}
}, 'b-form-rating', Object.assign({}, field), false)) : field.type && _vm.selectedRow === data.index && _vm.selectedCell === field.key && field.editable ? _c('b-form-input', _vm._b({
}, 'b-form-rating', Object.assign({}, field), false)) : field.type && _vm.tableItems[data.index].isEdit && _vm.selectedCell === field.key && field.editable ? _c('b-form-input', _vm._b({
directives: [{
name: "focus",
rawName: "v-focus"
}],
key: index,
attrs: {
"type": field.type
"type": field.type,
"value": _vm.tableItems[data.index][field.key]
},
on: {
"keydown": function ($event) {
return _vm.handleKeydown($event, index, data);
},
"input": function ($event) {
return _vm.$emit('input-change', $event, data);
"input": function (value) {
return _vm.inputHandler(value, data, field.key);
}
},
model: {
value: _vm.items[data.index][field.key],
callback: function ($$v) {
_vm.$set(_vm.items[data.index], field.key, $$v);
},
expression: "items[data.index][field.key]"
}
}, 'b-form-input', Object.assign({}, field), false)) : _c('span', {
key: index,
Expand Down Expand Up @@ -12318,7 +12311,7 @@ var __vue_staticRenderFns__ = [];

const __vue_inject_styles__ = function (inject) {
if (!inject) return;
inject("data-v-1f18c6de_0", {
inject("data-v-2461a8bf_0", {
source: ".data-cell{display:flex;width:100%}",
map: undefined,
media: undefined
Expand Down
2 changes: 1 addition & 1 deletion dist/b-editable-table.min.js

Large diffs are not rendered by default.

Loading

0 comments on commit d85f5d0

Please sign in to comment.