Skip to content

Instantly share code, notes, and snippets.

@minsis
Last active October 12, 2020 21:45
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save minsis/7706aba675e95172b404bac9ec394133 to your computer and use it in GitHub Desktop.
Save minsis/7706aba675e95172b404bac9ec394133 to your computer and use it in GitHub Desktop.
Bootstrap table editing value in place
.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;
}
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