Last active
October 12, 2020 21:45
-
-
Save minsis/7706aba675e95172b404bac9ec394133 to your computer and use it in GitHub Desktop.
Bootstrap table editing value in place
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
.editvalueform { | |
display: block; | |
} | |
.editvalue-link, .editvalue-link:hover { | |
border-bottom: 1px dotted blue; | |
text-decoration: none; | |
} | |
.editvalue-input, .editvalue-buttons { | |
display: inline-flex; | |
} | |
.editvalue-input { | |
width: 165px; | |
} | |
.control-group { | |
width: 100%; | |
display: inline-block; | |
} | |
.editvalue-text-field { | |
height: calc(1.5em + 0.75rem + 2px); | |
padding: 0.375rem 0.75rem; | |
font-size: 1rem; | |
width: 100%; | |
font-weight: 400; | |
line-height: 1.5; | |
color: #495057; | |
background-color: #fff; | |
background-clip: padding-box; | |
border: 1px solid #ced4da; | |
border-radius: 0.25rem; | |
white-space: nowrap; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const Utils = $.fn.bootstrapTable.utils | |
$.extend($.fn.bootstrapTable.defaults, { | |
editvalue: true | |
}) | |
$.extend($.fn.bootstrapTable.defaults.icons, { | |
editValueOk: 'fa-check', | |
editValueCancel: 'fa-times' | |
}) | |
$.extend($.fn.bootstrapTable.columnDefaults, { | |
alwaysUseFormatter: false | |
}) | |
const killAlerts = () => { | |
$('.alert').each((index, alert) => { | |
setTimeout(() => { | |
$(alert).fadeTo(500, 0).slideUp(500, () => { | |
}); | |
}, (index + 5) * 1000); | |
}); | |
} | |
$.BootstrapTable = class extends $.BootstrapTable { | |
initTable () { | |
super.initTable() | |
if (!this.options.editvalue) { | |
return | |
} | |
this.editedCells = [] | |
$.each(this.columns, (i, column) => { | |
if (!column.editvalue) { | |
return | |
} | |
const editvalueOptions = {} | |
const editvalueDataMarkup = [] | |
const editvalueDataPrefix = 'editvalue-' | |
const processDataOptions = (key, value) => { | |
// Replace camel case with dashes. | |
const dashKey = key.replace(/([A-Z])/g, $1 => `-${$1.toLowerCase()}`) | |
if (dashKey.indexOf(editvalueDataPrefix) === 0) { | |
editvalueOptions[dashKey.replace(editvalueDataPrefix, 'data-')] = value | |
} | |
} | |
$.each(this.options, processDataOptions) | |
column.formatter = column.formatter || (value => value) | |
column._formatter = column._formatter ? column._formatter : column.formatter | |
column.formatter = (value, row, index) => { | |
let result = Utils.calculateObjectValue(column, column._formatter, [value, row, index], value) | |
result = typeof result === 'undefined' || result === null ? this.options.undefinedText : result | |
if (this.options.uniqueId !== undefined && !column.alwaysUseFormatter) { | |
const uniqueId = Utils.getItemField(row, this.options.uniqueId, false) | |
if ($.inArray(column.field + uniqueId, this.editedCells) !== -1) { | |
result = value | |
} | |
} | |
$.each(column, processDataOptions) | |
$.each(editvalueOptions, (key, value) => { | |
editvalueDataMarkup.push(` ${key}="${value}"`) | |
}) | |
let noEditFormatter = false | |
const editvalueOpts = Utils.calculateObjectValue(column, | |
column.editvalue, [index, row], {}) | |
if (editvalueOpts.hasOwnProperty('noEditFormatter')) { | |
noEditFormatter = editvalueOpts.noEditFormatter(value, row, index) | |
} | |
if (noEditFormatter === false) { | |
return `<a href="#" | |
data-name="${column.field}" | |
data-pk="${row[this.options.idField]}" | |
data-value="${result}" | |
class="editvalue-link" | |
${editvalueDataMarkup.join('')}>${result}</a>` | |
} | |
return noEditFormatter | |
} | |
}) | |
} | |
initBody (fixedScroll) { | |
super.initBody(fixedScroll) | |
const formtemplate = '<form class="form-inline editvalueform">' + | |
' <div class="control-group">' + | |
' <div class="editvalue-input">' + | |
' <input type="text" class="editvalue-text-field">' + | |
' </div>' + | |
' <div class="editvalue-buttons">' + | |
' <button type="submit" class="btn btn-primary editvalue-submit">' + | |
` <i class="${this.options.iconsPrefix} ${this.options.icons.editValueOk}"></i>` + | |
' </button>' + | |
' <button type="button" class="btn btn-secondary editvalue-cancel">' + | |
` <i class="${this.options.iconsPrefix} ${this.options.icons.editValueCancel}"></i>` + | |
' </button>' + | |
' </div>' + | |
' <div class="editvalue-error-block"></div>' + | |
' </div>' + | |
'</form>' | |
if (!this.options.editvalue) { | |
return | |
} | |
$.each(this.columns, (i, column) => { | |
if (!column.editvalue) { | |
return | |
} | |
const $field = this.$body.find(`a[data-name="${column.field}"]`) | |
$field.each((i, element) => { | |
const $element = $(element) | |
$element.click(() => { | |
if (!$element.data('bs.popover')) { | |
$element.popover({ | |
container: 'body', | |
content: formtemplate, | |
html: true, | |
sanitize: false, | |
trigger: 'manual' | |
}).css({ | |
display: 'inline-block', | |
whiteSpace: "nowrap" | |
}) | |
} | |
$element.popover('toggle') | |
}) | |
}) | |
$field.on('inserted.bs.popover', (e) => { | |
const $this = $(e.currentTarget) | |
const $popover = $(`#${$this.attr('aria-describedby')}`) | |
const $buttonCancel = $($popover.find('.editvalue-cancel')[0]) | |
const $form = $($popover.find('.editvalueform')[0]) | |
const $input = $($popover.find('input')[0]) | |
friconix_update( | |
if (column.editvalue.type) { | |
$input.attr('type', column.editvalue.type) | |
} | |
$form.submit((e) => { | |
const name = $this.data('name') | |
const pk = $this.data('pk') | |
if (column.editvalue.url) { | |
e.preventDefault() | |
$.ajax({ | |
type: 'POST', | |
url: column.editvalue.url, | |
data: { | |
pk: pk, | |
value: $input.val(), | |
name: name, | |
}, | |
success: (response) => { | |
if (response.status === 0) { | |
const alertBox = $('.floating-alert-box') | |
const rowIndex = $this.parents('tr[data-index]').data('index') | |
this.data[rowIndex][response.data.field] = response.data.value | |
$this.popover('toggle') | |
$this.popover('dispose') | |
this.initBody(true) | |
alertBox.append(`<div class="alert alert-${response.category} alert-dismissible shadow" role="alert">${response.message}<i data-dismiss="alert" class="close-alert fi-ctlnxx-times-solid"></i></div>`) | |
killAlerts() | |
} | |
} | |
}) | |
} | |
}) | |
$buttonCancel.click(() => { | |
$this.popover('toggle') | |
}) | |
}) | |
$field.on('shown.bs.popover', ({ currentTarget }) => { | |
const $this = $(currentTarget) | |
const data = this.getData() | |
const rowIndex = $this.parents('tr[data-index]').data('index') | |
const row = data[rowIndex] | |
const $input = $($(`#${$this.attr('aria-describedby')}`).find('input')[0]) | |
$input.val(row[$this.data('name')]) | |
// this.trigger('editvalue-shown', column.field, row, $this, editvalue) | |
}) | |
}) | |
} | |
getData (params) { | |
const data = super.getData(params) | |
if (params && params.escape) { | |
for (const row of data) { | |
for (const [key, value] of Object.entries(row)) { | |
row[key] = Utils.unescapeHTML(value) | |
} | |
} | |
} | |
return data | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment