Skip to content

Commit

Permalink
Merge pull request #1063 from bindoon/fix-field-deepcopy
Browse files Browse the repository at this point in the history
fix(Field): shallow copy. Close #1062
  • Loading branch information
youluna authored Aug 28, 2019
2 parents 42555dd + 97ffea6 commit a631db4
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 25 deletions.
42 changes: 17 additions & 25 deletions src/field/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ class Field {
this.instance = {};
// holds constructor values. Used for setting field defaults on init if no other value or initValue is passed.
// Also used caching values when using `parseName: true` before a field is initialized
this.values = options.values || {};
this.values = Object.assign({}, options.values);

this.options = Object.assign(
{
Expand Down Expand Up @@ -66,10 +66,6 @@ class Field {
].forEach(m => {
this[m] = this[m].bind(this);
});

if (options.values) {
this.setValues(options.values, false);
}
}

setOptions(options) {
Expand Down Expand Up @@ -98,8 +94,6 @@ class Field {
const defaultValueName = `default${valueName[0].toUpperCase()}${valueName.slice(
1
)}`;

const field = this._getInitMeta(name);
let defaultValue;
if (typeof initValue !== 'undefined') {
defaultValue = initValue;
Expand All @@ -108,6 +102,8 @@ class Field {
defaultValue = originalProps[defaultValueName];
}

// get field from this.fieldsMeta or new one
const field = this._getInitMeta(name);
Object.assign(field, {
valueName,
initValue: defaultValue,
Expand All @@ -130,34 +126,30 @@ class Field {
}
}

// should get value from this.values
/**
* a new field (value not in field)
* step 1: get value from this.values
* step 2: from defaultValue
* first init field (value not in field)
* should get field.value from this.values or defaultValue
*/
if (!('value' in field)) {
if (parseName) {
const cachedValue = getIn(this.values, name);
field.value =
typeof cachedValue !== 'undefined'
? cachedValue
: defaultValue;
if (typeof cachedValue !== 'undefined') {
field.value = cachedValue;
} else if (typeof defaultValue !== 'undefined') {
field.value = defaultValue;
this.values = setIn(this.values, name, field.value);
}
} else {
const cachedValue = this.values[name];
field.value =
typeof cachedValue !== 'undefined'
? cachedValue
: defaultValue;
if (typeof cachedValue !== 'undefined') {
field.value = cachedValue;
} else if (typeof defaultValue !== 'undefined') {
field.value = defaultValue;
this.values[name] = field.value;
}
}
}

if (parseName && !getIn(this.values, name)) {
this.values = setIn(this.values, name, field.value);
} else if (!parseName && !this.values[name]) {
this.values[name] = field.value;
}

// Component props
const inputProps = {
'data-meta': 'Field',
Expand Down
24 changes: 24 additions & 0 deletions test/field/options-spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,30 @@ describe('options', () => {
})

describe('values', () => {
it('should shallow copy values with parseName=false', function() {
const inputValues = {a: 1, b: 2};
const field = new Field(this, {
values: inputValues,
});
field.setValue('b', 20);

assert.equal(field.getValue('b'), 20);
assert.equal(inputValues.b, 2);
});
it('should shallow copy values with parseName=true', function() {
const inputValues = { a: [1, 2, 3, 4], b: { c: 5}};
const field = new Field(this, {
parseName: true,
values: inputValues,
});
field.setValue('a.0', 100);
assert.equal(field.getValue('a.0'), 100);
assert.equal(inputValues.a[0], 1);

field.setValue('b.c', 50);
assert.equal(field.getValue('b.c'), 50);
assert.equal(inputValues.b.c, 5);
});
it('should set default field input values when given `values` in constructor', function() {
const inputValue = 'my value';
const field = new Field(this, {
Expand Down

0 comments on commit a631db4

Please sign in to comment.