Fix changing property name not working for arrays and objects

This commit is contained in:
josdejong 2020-05-03 19:44:55 +02:00
parent 7646c1756b
commit 3a9a409fcb
3 changed files with 39 additions and 41 deletions

View File

@ -7,7 +7,7 @@
export let searchText = '' export let searchText = ''
let json = { export let json = {
'array': [1, 2, 3, { 'array': [1, 2, 3, {
name: 'Item ' + 2, name: 'Item ' + 2,
id: String(2), id: String(2),
@ -102,7 +102,7 @@
} }
function handleChangeValue (value, key) { function handleChangeValue (value, key) {
console.log('App handleChangeValue') console.log('App handleChangeValue', value, key)
json = value json = value
} }

View File

@ -5,7 +5,7 @@
import classnames from 'classnames' import classnames from 'classnames'
import { isUrl, stringConvert, valueType } from './utils/typeUtils' import { isUrl, stringConvert, valueType } from './utils/typeUtils'
import { escapeHTML } from './utils/stringUtils.js' import { escapeHTML } from './utils/stringUtils.js'
import { createUpdateProps } from './utils/updateProps.js' import { updateProps } from './utils/updateProps.js'
import { unescapeHTML } from './utils/stringUtils' import { unescapeHTML } from './utils/stringUtils'
export let key = undefined export let key = undefined
@ -18,19 +18,18 @@
const DEFAULT_LIMIT = 100 const DEFAULT_LIMIT = 100
const escapeUnicode = false // TODO: pass via options const escapeUnicode = false // TODO: pass via options
// create lazy, memoized updateProps function
let updateProps = function lazyUpdateProps (value) {
updateProps = createUpdateProps()
return updateProps(value)
}
let limit = DEFAULT_LIMIT let limit = DEFAULT_LIMIT
$: type = valueType (value) $: type = valueType (value)
$: props = type === 'object' let prevValue = undefined
? updateProps(value) let props = updateProps(value)
: undefined
$: if (value !== prevValue) {
prevValue = value
props = updateProps(value, props)
}
$: limited = type === 'array' && value.length > limit $: limited = type === 'array' && value.length > limit
@ -96,8 +95,15 @@
const index = props.findIndex(item => item.key === oldChildKey) const index = props.findIndex(item => item.key === oldChildKey)
if (index !== -1) { if (index !== -1) {
// FIXME: make immutable (not possible as long as prevProps is stored in updateProps // we use splice here to replace the old key with the new new one
props[index].key = newChildKey // already without Svelte noticing it (no assignment), so we prevent
// a needless render. We keep the same id, so the child HTML will be
// reused
// TODO: is there a better way to do this?
props.splice(index, 1, {
id: props[index].id,
key: newChildKey
})
} }
onChangeValue(updatedValue, key) onChangeValue(updatedValue, key)

View File

@ -1,34 +1,26 @@
import { isObject } from './typeUtils.js' import { isObject } from './typeUtils.js'
import uniqueId from 'lodash/uniqueId.js' import uniqueId from 'lodash/uniqueId.js'
export function createUpdateProps () { export function updateProps (value, prevProps) {
let prevProps = undefined if (isObject(value)) {
// copy the props that still exist
const props = prevProps
? prevProps.filter(item => value[item.key] !== undefined)
: []
return function updateProps (value) { // add new props
// TODO: optimize. check if value is the same as prevValue, if so, don't do anything const prevKeys = new Set(props.map(item => item.key))
Object.keys(value).forEach(key => {
if (!prevKeys.has(key)) {
props.push({
id: uniqueId(),
key
})
}
})
if (isObject(value)) { return props
const props = prevProps } else {
? prevProps.filter(item => value[item.key] !== undefined) // copy the props that still exist return undefined
: []
// process added props
const prevKeys = new Set(props.map(item => item.key)) // TODO: this is inefficient, creating a set. cache this set?
Object.keys(value).forEach(key => {
if (!prevKeys.has(key)) {
props.push({
id: uniqueId(),
key
})
}
})
prevProps = props
return props
} else {
prevProps = undefined
return undefined
}
} }
} }