Jenesius / vue-form

💪 Heavy form system for Vue.js v3
http://form.jenesius.com
MIT License
45 stars 4 forks source link

Class inheritance #96

Closed Jenesius closed 1 year ago

Jenesius commented 1 year ago

On current momen we have next classes: Form, ProxyForm, Input ProxyForm -> Form Form -> EventEmitter Input -> EventEmitter

I think we need to expand this solution and create diagram:

             | - - - > FormItem - - - > Input(FormField)
EventEmitter |
             | - - - > SimpleForm - - - > ProxyForm
                           |
                           | - - - > Form
Jenesius commented 1 year ago

Нужно продумать следующее:

  1. Установка значений в родительской форме, form.setValues
  2. Установка значения через ввода в поле ввода
  3. Установка значения в дочерней ProxyForm
  4. Установка значения через ввод в поле ввода в ProxyForm
Jenesius commented 1 year ago

Нужна ли тогда вообще ProxyForm

Jenesius commented 1 year ago

Если есть parentFrom и name. Мы так упростим работу

Jenesius commented 1 year ago

Основная проблема рекурсию в которую мы упираемся

Jenesius commented 1 year ago

Для решения рекурсии предлагается использовать следующую модель:

  1. Все данные, являющиеся частью модели формы, то есть хранящиеся в форме и являющиеся состоянием (значение, изменение, доступность) - должны:
    • Всегда передаваться из дочернего наверх и никогда вниз.
    • В родительском элементе полученное значение преобразуется и генерируются события, на которые подписаны дочерние элементы ИЛИ вызываются соответствующие методы для изменения (Тут нужно подумать, т.к. это и есть проблема рекурсии, однако данный подход наиболее симпатичен)
    • Все значения полей состояния (values, changes, disabled, changed) являются динамическими и для них должен быть установлен getter на получения значения из родителя (Если родитель установлен: this.parent !== null)
Jenesius commented 1 year ago

Нужно продумать, чтобы при cleanValues/cleanField форма правильно обрабатывало это

Jenesius commented 1 year ago

image Новая бага. Не находит изменения при перезаписывании объекта.

Jenesius commented 1 year ago

Столкнулся с проблемой сравнения объекта, в случае, если во вложенный объект приходит: New value:

{
  name: "Jenesius",
  age: 23
}

Old value:

{
  name: "Jenesius",
  age: 24
}

В таком случае дочерний элемент может либо все поля уведомить, как изменённые, а может сравнить(повторно) и уведомить только про изменение в поле age

Jenesius commented 1 year ago

А что, если oninput в дочернем элементе подписывать сразу на родителя? И так может по цепочке до самого верха

Jenesius commented 1 year ago

Oninput передавать в родительский плохая идея, т.к. непонятно потом как чистить это и т.д. Теперь курс взят на CompareEvent И из него уже получать нужное через event.revertByName('coordinate') Таким образом мы получим в новый эвент, но уже со списком изменения для координат, что может быть очень удобным решением.

Jenesius commented 1 year ago

Документация описана. Теперь нужно более чётко описать принцип обновления данных. Составить схему обновления.

Jenesius commented 1 year ago

DONE Работа со значениями успешно выполнена, установка, очистка. NEXT Работа с изменениями: changes, пометка изменений, очистка изменений.

Jenesius commented 1 year ago

Продумать, как не делать G.M.

Jenesius commented 1 year ago

Продумать систему отката изменения. В данной реализации система changes реализована не прозрачно. Непонятно, как себя будет вести форма при изменении одного из элементов вложенности. Под вложенностью подразумевается ,например, адрес. Если Address.city был изменён, в каком состоянии находится сам address? По идеи в состоянии changed. Если один из дочерних элементов находится в состоянии changed, значит и родитель находится в состоянии changed = true.

Теперь необходимо описать хранилище изменений. У формы может быть состояние, хранимое в values. В текущей реализации changes представляют из себя слепок, где изменённое значение помечается как true (в объекте changes), а само значение хранится всё также в values. В новой реализации можно разнести это по двум разным объектам. Первый хранит в себе значения, которые были установлены через setValues (Без пометки changed). При изменении значений, используя метод change или setValus(data, {changes: true}) (Для этого нужно расширить метод setValue), мы можем устанавливать значения в переменную changes. Таким образом:

Теперь необходимо продумать, как хранить и как смешивать эти значения.

Расширить

Jenesius commented 1 year ago

Проблема новая в том, как должна вести себя форма, если было сделано следующее:

form.setValues({name: "Jenesius"})
form.change({name: "Burd"})
form.setValues({name: "Burdin"})

Что должно отображаться на форме

Jenesius commented 1 year ago

Данный способ не подходит. Для реализации функции revert нужно придумать обходной механизм. Грубо говоря

const {revert} = useInitialValues(form)

Данная функция, будет подписываться на values, затем при изменении формы возвращать её к первоначальному состоянию

Jenesius commented 1 year ago

Либо упростить механизм. В приведённом примере сверху:

#values(Private):

{
  "name": "Jenesius"
}

changes(Public):

{
  "name": "Burd"
}

values(Public):

{
  "name": "Burd"
}

Итог: form.values является merged результатом #changes и #values

{
  "name": "Burdin"
}
Jenesius commented 1 year ago

В данном подходе есть проблема с замещением значения.

Шаг 1

form.setValues(values); values:

{
  "address": {
    "city": "Mogilev",
    "country": "Russia"
  }
}

Шаг 2

form.setValues(changes, { changes: true, clean: true }) changes:

{
  "address": {
    "index": 123
  }
}

Результат

В таком случае, с changes будет лежать { index: 123 } и при merge с #changes, мы получим, что form.values равен:

{
  "address": {
    "city": "Mogilev",
    "country": "Russia",
    "index": 123
  }
}
Jenesius commented 1 year ago

В данном случае можно использовать прототипные свойства объекта. Например добавить свойство clea: true, и по нему уже строить результат.

Jenesius commented 1 year ago

Хорошее предложение использовать this и prototype. Работаю в эту сторону

Jenesius commented 1 year ago

в данной задаче можно реализовать ещё event system: form.onstate = (FormStateEvent) => {}

Jenesius commented 1 year ago

В данном подходе есть проблема с замещением значения.

Шаг 1

form.setValues(values); values:

{
  "address": {
    "city": "Mogilev",
    "country": "Russia"
  }
}

Шаг 2

form.setValues(changes, { changes: true, clean: true }) changes:

{
  "address": {
    "index": 123
  }
}

Результат

В таком случае, с changes будет лежать { index: 123 } и при merge с #changes, мы получим, что form.values равен:

{
  "address": {
    "city": "Mogilev",
    "country": "Russia",
    "index": 123
  }
}

Разве тут не должно быть: Values:

{
  "city": null,
  "country": null,
  "index": 123
}

Для этого в конфиге можно добавить поле defaultCleanValue: null

Jenesius commented 1 year ago

Также нужно решить проблему с передачей options наверх родителей

Jenesius commented 1 year ago

Написать тесты для clean

Jenesius commented 1 year ago

За сегодня нужно добить setValues, cleanValues и т.д. Затем уже перейти на Available

Jenesius commented 1 year ago

Также такие поля, как ID и version также должны присутствовать в классе, а также реагировать на изменения on("id", callback) on("version, )

Jenesius commented 1 year ago

Очистка полей, для которых затрагивалось setValues при change: false - готова. Нашёлся новый баг:

form.setValues({'username.name.jenesius': "Jenesius"})

При этому pureValues:

{
  "username": {
    "name": {
      "jenesius": "Jenesius"
    }
  },
  "username.name": {
    "jenesius": "Jenesius"
    },
  "username.name.jenesius": "Jenesius"
}

Скорее всего это связано с тем, что мы идём по compareResult и затрагиваем всё

Jenesius commented 1 year ago

Данная задача является выполненной. Полностью были реализованы setValues и следующие параметры: clean, change, target