У меня сложная форма, которая содержит множество вопросов. Каждый набор может быть добавлен в форму несколько раз. Примером является JSON, который я получаю с сервера.
{
"Form": {
"Level1Id": 2,
"DisplayName": "Liabilities",
"UniqueCode": "$L1_TL",
"Level2s": [
{
"Id": 3,
"UniqueCode": "$L2_TL_CR",
"DisplayName": "Credits",
"MaxOccurs": null,
"Level2Groups": [
{
"GroupId": "3",
"QuestionsWithAnswers": [
{
"DisplayName": "Remain",
"InputType": 4,
"UniqueCode": "$L3_CR_RMN",
"GroupId": "3",
"AnswerId": 3,
"Answer": "10000",
"Id": 5
},
{
"DisplayName": "Monthly Payment",
"InputType": 4,
"UniqueCode": "$L3_CR_PMN",
"GroupId": "3",
"AnswerId": 4,
"Answer": "1000",
"Id": 6
},
{
"DisplayName": "Last Payment Date",
"InputType": 10,
"UniqueCode": "$L3_CR_ED",
"GroupId": "3",
"AnswerId": 5,
"Answer": "2020-10-28 11:21:18.926961",
"Id": 7
}
]
}
]
}
]
},
"Total": 6
}
Level2s - это массив, содержащий группы вопросов (Level2Groups). У каждой группы есть QuestionsWithAnswers, где каждый элемент представляет некоторый вход со значением в нем (ответ). Что мне нужно сделать, так это, если элемент Level2s имеет MaxOccurs> 1 или ноль, чтобы добавить группу в Level2Groups для определенного элемента Level2s.
Я использую Mobx как магазин для хранения всей этой информации о форме. Я даже могу добавить элемент туда, где мне нужно, и вызывается rerender, но ничего не меняется в представлении.
А также у меня проблема с размещением ответа в магазине.
Вот код для реакции. (не весь код, только важные части)
Магазин Mobx:
@observable
form = {
DisplayName: "L1Name",
}
@observable
lvl2s = [];
//here I get JSON from server
@action
setData(data) {
debugger;
this.form = data.Form;
this.lvl2s = data.Form.Level2s;
super.setData();
}
@action
addCategoryToLevel(levelId) {
debugger;
var copy = toJS(this.lvl2s);
const filteredArray = this.lvl2s.filter(item => item.Id === levelId);
const QAs = filteredArray[0].Level2Groups[0].QuestionsWithAnswers;
const copyQAs = [];
const grId = uuid();
for (let i = 0; i < QAs.length; i++) {
copyQAs.push(
{
DisplayName: QAs[i].DisplayName,
UniqueCode: QAs[i].UniqueCode,
InputType: QAs[i].InputType,
Id: QAs[i].Id,
Answer: null,
AnswerId: 0,
MaxOccurs: QAs[i].MaxOccurs,
})
}
var newQQ = filteredArray[0].Level2Groups.concat({ GroupId: grId, QuestionsWithAnswers: copyQAs });
filteredArray[0].Level2Groups = newQQ;
var newAll = [];
this.lvl2s.map(item => {
if (item.Id !== levelId)
newAll.push(toJS(item));
else
newAll.push(filteredArray[0]);
});
debugger;
this.lvl2s.replace(newAll);//from Mobx docs
// I replace everything with new values, where the desired things are added
}
Вот базовый компонент, с которого начинается магия:
render() {
const { form, lvl2s } = this.formStore;
return (
<WizardForm form={form} lvl2s={lvl2s}/>
);}
Вот компонент WizardFrom:
@observer
export class WizardForm extends React.Component {
constructor(props) {
super(props);
this.formStore = getComp('QuestionFormStore');
this.state = {
form: props.form,
}
}
render() {
debugger;
const { form } = this.state;
const { lvl2s } = this.formStore;
//lvl2s is the array that was changed. I call toJS to check what is inside
//after I add a new group the structure is correct, but the new elements won't show up
const ss = toJS(lvl2s);
return (
<div>
<h2>{form.DisplayName}</h2>
{lvl2s.map((level2, i) => {
debugger;
return (<div>
<h3 >{level2.DisplayName}</h3>
<WizardStepCategory groups={level2.Level2Groups} maxOccurs={level2.MaxOccurs} levelId={level2.Id} />
</div>);
})}
</div>
);
}
}
Вот компонент WizardStepCategory:
@observer
export class WizardStepCategory extends React.Component {
constructor(props) {
super(props);
this.state = {
groups: props.groups,
maxOccurs: props.maxOccurs,
levelId: props.levelId,
}
this.formStore = getComp('QuestionFormStore');
}
@action
handleClick(event) {
debugger;
this.formStore.addCategoryToLevel(this.state.levelId);
//here I add a new set of questions with answer
}
render() {
debugger;
const { groups, maxOccurs } = this.state;
return (
<div>
{groups.map((group, i) => {
debugger;
const canAdd = (maxOccurs == null) | ((maxOccurs > 1) & groups.length < maxOccurs);
return <div >
<WizardQuestion questionsWithAnswers={group.QuestionsWithAnswers} groupId={group.GroupId} />
{canAdd && <button onClick={(event) => this.handleClick(group, event)}>ADD</button>}
</div>
})}
</div>
);
}
}
И, наконец, компонент WizardQuestion.
@observer
export class WizardQuestion extends React.Component {
constructor(props) {
super(props);
this.state = {
questionsWithAnswers: props.questionsWithAnswers,
groupId: props.groupId,
}
}
handleValueChange(value, question) {
debugger;
question.Answer = value.floatValue;
}
render() {
debugger;
const { questionsWithAnswers, maxOccurs, groupId } = this.state;
return (
<div>
{questionsWithAnswers.map((question, i) => {
let inputEl;
if (question.InputType === 4)
inputEl = <DecimalInput answer={question.Answer} question={question} handleValueChange={this.handleValueChange} />; }
return <div key={i}>
{question.DisplayName}
<br />
{inputEl}
</div>
})}
</div>
);
}
}
Это изображение того, как оно выглядит. При нажатии кнопки ДОБАВИТЬ должны появиться 3 новых элемента ввода. И когда я изменяю текущий шаг формы, я хочу сохранить все ответы, передав мой FormStore на сервер. Но я не могу поставить ответы в магазине. Может быть, есть лучший способ сделать что-то?