diff --git a/resources/js/bootstrap/globals.js b/resources/js/bootstrap/globals.js index a1516c273d..528d8ec8fe 100644 --- a/resources/js/bootstrap/globals.js +++ b/resources/js/bootstrap/globals.js @@ -1,5 +1,6 @@ import { marked } from 'marked'; import { translate, translateChoice } from '../translations/translator'; +import { default as set } from './set'; export function cp_url(url) { url = Statamic.$config.get('cpUrl') + '/' + url; @@ -34,6 +35,10 @@ export function data_get(obj, path, fallback=null) { return value !== undefined ? value : fallback; }; +export function data_set(obj, path, value) { + set(obj, path.split('.'), value); +} + export function clone(value) { if (value === undefined) return undefined; diff --git a/resources/js/bootstrap/set.js b/resources/js/bootstrap/set.js new file mode 100644 index 0000000000..a135ad7834 --- /dev/null +++ b/resources/js/bootstrap/set.js @@ -0,0 +1,37 @@ +import isObject from 'underscore/modules/isObject.js'; +import toPath from 'underscore/modules/_toPath.js'; +import contains from 'underscore/modules/contains.js'; + + +var arrayIndex = /^\d+$/; + +// Internal function of `set`. +function deepSet(obj, path, value) { + var key = path[0]; + + if (path.length === 1) { + obj[key] = value; + return; + } + + if (!isObject(obj[key])) { + var nextKey = path[1]; + obj[key] = arrayIndex.test(nextKey) ? [] : {}; + } + + return deepSet(obj[key], path.slice(1), value); +} + +// Set the value on `path` of `object`. +// If any property in `path` does not exist it will be created. +// Returns mutated object (`obj`). +export default function set(obj, path, value) { + path = toPath(path); + + if (!isObject(obj) || !path.length) return obj; + if (contains(path, '__proto__')) throw new Error('Prototype assignment attempted'); + + deepSet(obj, path, value); + + return obj; +} diff --git a/resources/js/components/publish/Container.vue b/resources/js/components/publish/Container.vue index fbfd50faba..4faade5aea 100644 --- a/resources/js/components/publish/Container.vue +++ b/resources/js/components/publish/Container.vue @@ -111,7 +111,7 @@ export default { mutations: { setFieldValue(state, payload) { const { handle, value } = payload; - state.values[handle] = value; + data_set(state.values, handle, value); }, setValues(state, values) { state.values = values;