Fix #926: Keep order of properties when updating an object

This commit is contained in:
jos 2020-03-18 09:37:44 +01:00
parent 341cc2ca8e
commit 2316c87a46
3 changed files with 46 additions and 22 deletions

View File

@ -2,9 +2,9 @@
https://github.com/josdejong/jsoneditor
## not yet published, version 8.6.2
- Fixed #926: Keep order of properties when updating an object.
- Fixed #928: Custom root name not reflected in path of navigation bar.
- Upgraded to `ajv@6.12.0`

View File

@ -416,7 +416,7 @@ export class Node {
setValue (value, type) {
let childValue, child, visible
let i, j
const notUpdateDom = false
const updateDom = false
const previousChilds = this.childs
this.type = this._getType(value)
@ -454,7 +454,7 @@ export class Node {
value: childValue
})
visible = i < this.getMaxVisibleChilds()
this.appendChild(child, visible, notUpdateDom)
this.appendChild(child, visible, updateDom)
}
}
}
@ -462,7 +462,7 @@ export class Node {
// cleanup redundant childs
// we loop backward to prevent issues with shifting index numbers
for (j = this.childs.length; j >= value.length; j--) {
this.removeChild(this.childs[j], notUpdateDom)
this.removeChild(this.childs[j], updateDom)
}
} else if (this.type === 'object') {
// object
@ -474,7 +474,7 @@ export class Node {
// we loop backward to prevent issues with shifting index numbers
for (j = this.childs.length - 1; j >= 0; j--) {
if (!hasOwnProperty(value, this.childs[j].field)) {
this.removeChild(this.childs[j], notUpdateDom)
this.removeChild(this.childs[j], updateDom)
}
}
@ -483,20 +483,25 @@ export class Node {
if (hasOwnProperty(value, childField)) {
childValue = value[childField]
if (childValue !== undefined && !(childValue instanceof Function)) {
child = this.findChildByProperty(childField)
const childIndex = this.childs.findIndex(child => child.field === childField)
child = this.childs[childIndex]
if (child) {
// reuse existing child, keep its state
child.setField(childField, true)
child.setValue(childValue)
// change the index of the property such that it matches the index of the updated JSON
if (childIndex !== i) {
this.moveBefore(child, this.childs[i])
}
} else {
// create a new child
child = new Node(this.editor, {
field: childField,
value: childValue
})
visible = i < this.getMaxVisibleChilds()
this.appendChild(child, visible, notUpdateDom)
this.insertBefore(child, this.childs[i], updateDom)
}
}
i++
@ -1012,8 +1017,11 @@ export class Node {
* Only applicable when Node value is of type array or object
* @param {Node} node
* @param {Node} beforeNode
* @param {boolean} [updateDom] If true (default), the DOM of both parent
* node and appended node will be updated
* (child count, indexes)
*/
moveBefore (node, beforeNode) {
moveBefore (node, beforeNode, updateDom) {
if (this._hasChilds()) {
// create a temporary row, to prevent the scroll position from jumping
// when removing the node
@ -1032,12 +1040,13 @@ export class Node {
// the this.childs.length + 1 is to reckon with the node that we're about to add
if (this.childs.length + 1 > this.visibleChilds) {
const lastVisibleNode = this.childs[this.visibleChilds - 1]
this.insertBefore(node, lastVisibleNode)
this.insertBefore(node, lastVisibleNode, updateDom)
} else {
this.appendChild(node)
const visible = true
this.appendChild(node, visible, updateDom)
}
} else {
this.insertBefore(node, beforeNode)
this.insertBefore(node, beforeNode, updateDom)
}
if (tbody) {
@ -1051,8 +1060,11 @@ export class Node {
* Only applicable when Node value is of type array or object
* @param {Node} node
* @param {Node} beforeNode
* @param {boolean} [updateDom] If true (default), the DOM of both parent
* node and appended node will be updated
* (child count, indexes)
*/
insertBefore (node, beforeNode) {
insertBefore (node, beforeNode, updateDom) {
if (this._hasChilds()) {
this.visibleChilds++
@ -1094,10 +1106,12 @@ export class Node {
this.showChilds()
}
if (updateDom !== false) {
this.updateDom({ updateIndexes: true })
node.updateDom({ recurse: true })
}
}
}
/**
* Insert a new child before a given node

View File

@ -22,16 +22,26 @@ if (typeof Element !== 'undefined') {
})()
}
// simple polyfill for Array.findIndex
if (!Array.prototype.findIndex) {
// eslint-disable-next-line no-extend-native
Array.prototype.findIndex = function (predicate) {
for (let i = 0; i < this.length; i++) {
const element = this[i]
if (predicate.call(this, element, i, this)) {
return i
}
}
return -1
}
}
// Polyfill for Array.find
if (!Array.prototype.find) {
// eslint-disable-next-line no-extend-native
Array.prototype.find = function (callback) {
for (let i = 0; i < this.length; i++) {
const element = this[i]
if (callback.call(this, element, i, this)) {
return element
}
}
Array.prototype.find = function (predicate) {
const i = this.findIndex(predicate)
return this[i]
}
}