For given code when onFieldChange is called, the computed property named editedFields is not updating. Any help will be appreciated.
class FormsBaseStore {
constructor() {
this.form = {};
}
//Filters the form fields that were edited
@ computed get editedFields() {
let arrEdited = [];
const fields = this.form.fields;
for (var field in fields) {
(fields[field].isEdited)
? arrEdited.push(fields[field])
: null;
}
return arrEdited;
}
//Use it to instantiate values to the form
@ action setFormData(fieldsObj) {
const {
id,
...fields
} = fieldsObj;
let newFieldsObj = {};
for (var field in fields) {
const newObjValue = (fields[field].value !== null && fields[field].value !== undefined) ? fields[field].value : "";
const newObjRule = (fields[field].rule) ? fields[field].rule : null;
(newObjValue !== undefined && newObjValue !== null && newObjValue !== "")
? newFieldsObj[field] = new FormField(field, newObjValue, )
: newFieldsObj[field] = new FormField(field, newObjValue);
}
this.form = new Form(newFieldsObj, id);
}
//this method is called on the onChange event of the form elements
@ action.bound onFieldChange(field, value) {
var fieldName = (typeof(field) === "string") ? field : field.target.name;
const form = this.form;
const formField = form.fields[fieldName];
//Setting item value
(value == undefined || value == null) ? value = "" : null;
let fieldValue = (value !== undefined && value !== "") ? value : (typeof(field) === "string") ? "" : field.target.value;
(fieldValue == undefined || fieldValue == null) ? fieldValue = "" : fieldValue;
formField.value = fieldValue;
//controlling edition
this.checkIfEdited(formField);
}
checkIfEdited = (field) => {
let value = field.value;
let defaultValue = field.defaultValue;
if (isObservable(field.defaultValue)) {
defaultValue = toJS(field.defaultValue);
value = toJS(field.value);
}
if (defaultValue !== value && !Array.isArray(defaultValue) && typeof defaultValue !== 'object') {
field.isEdited = true;
} else if ((Array.isArray(defaultValue) || typeof defaultValue === 'object') && !isEqual(defaultValue, value)) {
field.isEdited = true;
} else if (!field.isValid) {
field.isEdited = true;
} else {
field.isEdited = false;
field.container = null;
}
}
}
class Form {
constructor(fields, id) {
this.fields = fields;
this.meta.id = id;
}
@ observable fields = {};
@ observable meta = {
id: null
}
}
class FormField {
@ observable name;
@ observable value;
@ observable isEdited;
constructor(name = null, value = "", isEdited = false) {
this.name = name;
this.value = value;
this.isEdited = isEdited;
}
}
Please create a codesandbox.io example
On Tue, Feb 5, 2019, 2:41 PM gs-trader notifications@github.com wrote:
For given code when onFieldChange is called, the computed property named
editedFields is not updating. Any help will be appreciated.class FormsBaseStore {
constructor() {
this.form = {};
}//Filters the form fields that were edited
@ computed get editedFields() {
let arrEdited = [];const fields = this.form.fields; for (var field in fields) { (fields[field].isEdited) ? arrEdited.push(fields[field]) : null; } return arrEdited;}
//Use it to instantiate values to the form
@ action setFormData(fieldsObj) {const { id, ...fields } = fieldsObj; let newFieldsObj = {}; for (var field in fields) { const newObjValue = (fields[field].value !== null && fields[field].value !== undefined) ? fields[field].value : ""; const newObjRule = (fields[field].rule) ? fields[field].rule : null; (newObjValue !== undefined && newObjValue !== null && newObjValue !== "") ? newFieldsObj[field] = new FormField(field, newObjValue, ) : newFieldsObj[field] = new FormField(field, newObjValue); } this.form = new Form(newFieldsObj, id);}
//this method is called on the onChange event of the form elements
@ action.bound onFieldChange(field, value) {var fieldName = (typeof(field) === "string") ? field : field.target.name; const form = this.form; const formField = form.fields[fieldName]; //Setting item value (value == undefined || value == null) ? value = "" : null; let fieldValue = (value !== undefined && value !== "") ? value : (typeof(field) === "string") ? "" : field.target.value; (fieldValue == undefined || fieldValue == null) ? fieldValue = "" : fieldValue; formField.value = fieldValue; //controlling edition this.checkIfEdited(formField);}
checkIfEdited = (field) => {
let value = field.value;
let defaultValue = field.defaultValue;if (isObservable(field.defaultValue)) { defaultValue = toJS(field.defaultValue); value = toJS(field.value); } if (defaultValue !== value && !Array.isArray(defaultValue) && typeof defaultValue !== 'object') { field.isEdited = true; } else if ((Array.isArray(defaultValue) || typeof defaultValue === 'object') && !isEqual(defaultValue, value)) { field.isEdited = true; } else if (!field.isValid) { field.isEdited = true; } else { field.isEdited = false; field.container = null; }}
}
class Form {
constructor(fields, id) {
this.fields = fields;
this.meta.id = id;
}@ observable fields = {};
@ observable meta = {
id: null
}
}class FormField {
@ observable name;
@ observable value;
@ observable isEdited;constructor(name = null, value = "", isEdited = false) {
this.name = name; this.value = value; this.isEdited = isEdited;}
}
—
You are receiving this because you are subscribed to this thread.
Reply to this email directly, view it on GitHub
https://github.com/mobxjs/mobx/issues/1891, or mute the thread
https://github.com/notifications/unsubscribe-auth/AAIrcqbEZqaiOyDEZRjRTFrHyBbtR-iTks5vKeyUgaJpZM4akCEt
.
@gs-trader Base on the code ( and as @mattruby said, codesandbox would be better)
You computed is based on non observable data.
Your fields param, is Form's class member
doing this.form = new Form(newFieldsObj, id); in class FormsBaseStore, without making it an observable in this class also, will break observability.
see the docs section Don't copy observables properties and store them locally
computing other stores on a new store has some limits. you can see https://github.com/mobxjs/mobx/issues/715
@mattruby and @ItamarShDev Thanks for your quick responses. After your suggestion i created example version on codesandbox and it works there as is. So there is something in my code base that causing it.
Also to my surprise when this.forms is updated to @observable form = {}, the code base starts working. So probably there is some anomaly in code thats is responsible for this strange behavior.
@gs-trader Happy to hear that you manages to make it work in the codesandbox.
Hope you'll manage to fix it in your codebase too.
Seems like this issue should be closed.
@gs-trader yes, form must be declared as observable, otherwise mobx cannot track reassignments to that property! And you are reassinging it in setFormData: this.form = new Form(newFieldsObj, id);
A rule of thumb you can use: either all fields should be readonly or @observable. If it is neither, than you have something for which no changes can be tracked. Marking that field as readonly would have resulted in a compile error in typescript in the setFormData method.
@gs-trader if this matter is solved for you, please consider closing the issue
Closing for inactivity
This thread has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs or questions.