Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

#347 separate input name generator method from error field name gener… #357

Closed
wants to merge 3 commits into from
Closed

#347 separate input name generator method from error field name gener… #357

wants to merge 3 commits into from

Conversation

olegbaturin
Copy link

@olegbaturin olegbaturin commented Aug 25, 2021

  1. Возможные имена для input
    ClassName[attr][index][field]
    attr[index][field]

Если нет колонок или колонка одна и field есть в модели. Я бы добавил еще условие равенства имён attr=field.
ClassName[field][index]
field[index]
2. Метод для генерации input name используется и для генерации имени атрибута модели, на который будет присвоены ошибки. В этом изначальная причина бага. Имя атрибута для ошибок не обязательно привязывать к методу фреймворка для генерации input name. Заменять метод фреймворка для генерации input name не надо, чтобы не получать подобных багов.
3. Я бы добавил условие совпадения attr=name для генерации имени в виде ClassName[field][index] (field[index]).

@@ -125,10 +123,10 @@ public function getFirstError($index)
return null;
}

if ($this->isRendererHasOneColumn()) {
if ($this->isRendererHasOneColumn() && $this->hasModelAttribute($this->name)) {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

я не очень понимаю зачем тут проверка на hasModelAttribute, ведь я могу использовать одну колонку для поля которого нет в модели и в этом случае тоже должен быть одноколоночный формат имени

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Одна колонка может быть двух видов. Как самостоятельный атрибут и как колонка у атрибута:

  1. Как атрибут класса - для этого делается проверка наличия атрибута у класса. В этом случае ошибку будем вешать в объекте класса модели так $this->addError('field[1]', 'Ошибка у field №1')
<?= $form->field($model, 'field')->widget(MultipleInput::class, [
    'allowEmptyList' => true,
    'addButtonPosition' => MultipleInput::POS_FOOTER,
])->label(false); ?>

Результат длжен быть <input name="field[0]"> или <input name="ClassName[field][0]">. Т.е. как обычный атрибут, только в виде массива.

Такой же рузультат будет и при условии, что в опциях задана только одна колонка.

<?= $form->field($model, 'filter')->widget(MultipleInput::class, [
    'allowEmptyList' => true,
    'addButtonPosition' => MultipleInput::POS_FOOTER,
    'columns' => [
        [
            'name'  => 'field',
            'enableError' => true,
        ],
    ],
])->label(false); ?>

Но тут я считаю, что надо добавить еще проверку на совпадение $this->context->attribute и $this->name, иначе теряется значение атрибута 'filter' в данном примере.

  1. Как обычное поле у корневого атрибута.
    input name такое же, как и при нескольких колонках <input name="filter[0][from]"> или <input name="ClassName[filter][0][from]">. Ошибку будем вешать так $this->addError('filter[0][field]', 'Ошибка у filter №1, поле field').

я могу использовать одну колонку для поля которого нет в модели и в этом случае тоже должен быть одноколоночный формат имени

Если у класса нет атрибута, то будет исключение при присвоении ему значения.

Copy link
Owner

@unclead unclead Aug 26, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Если у класса нет атрибута, то будет исключение при присвоении ему значения.

ну так я могу использовать виджет вообще без модели и без ActiveForm

echo MultipleInput::widget([
    'id'                => 'my-input',
    'limit'             => 10,
    'allowEmptyList'    => false,
    'enableGuessTitle'  => true,
    'min'               => 2,
    'name'              => 'name'
]);

В контроллер при этом придет просто массив данных, который я уже по своему усмотрению могу обработать.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

и вот про этот пункт я тоже не до конца понял

<?= $form->field($model, 'filter')->widget(MultipleInput::class, [
    'allowEmptyList' => true,
    'addButtonPosition' => MultipleInput::POS_FOOTER,
    'columns' => [
        [
            'name'  => 'field',
            'enableError' => true,
        ],
    ],
])->label(false); ?>

в этом случае имя инпута должно быть ClassName['filter']['field'][0], иначе теряется весь смысл. Например, такой кейс вот в этом примере https://github.com/unclead/yii2-multiple-input/blob/master/examples/views/multiple-input.php#L51

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Надо значит добавлять проверку if ($model instanceof Model).
Нам же в итоге надо корректно сделать и для Model в том числе.

Copy link
Author

@olegbaturin olegbaturin Aug 26, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

в этом случае имя инпута должно быть ClassName['filter']['field'][0]

Тут смотря какая логика закладывается. Либо у нас массив значений атрибута с одним или несколькими полями, тогда будет один вид имени для input и для нескольких колонок и для одной. Т.е. у нас строка №1, 2, ... и в ней поля (одно или несколько). Я выбрал его для однообразия, чтобы не делать разные валидаторы для разных кейсов с одной логикой.

Второй вариант ['filter']['field'][0] - это атрибут, и у него массив колонки. Мне не очень понятна эта логика.

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

Имя всегда должно начинаться с ['filter'][0], чтобы общая логика не нарушалась.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Для примера. Был фильтр с одной колонкой. Добавили вторую. Либо было несколько колонок, оставили одну. Всегда имя у input должно быть одинаковым. Сейчас оно будет меняться при увеличении колонок от одной или уменьшении до одной.


if (!$withPrefix) {
return $elementName;
if ($this->isRendererHasOneColumn() && $this->hasModelAttribute($this->name)) {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

см. аналогичный комментарий ниже

@unclead
Copy link
Owner

unclead commented Aug 26, 2021

@olegbaturin а ты проверил, что весь функционал работает? 😄 Тестов то нифига нет 😄

@olegbaturin
Copy link
Author

olegbaturin commented Aug 26, 2021

@olegbaturin а ты проверил, что весь функционал работает? smile Тестов то нифига нет smile

Пофиксил для конфига без колонок. Проверял 4 кейса с/без классом в имени input.

  1. Колонок нет.
  2. Одна колонка и ее имя является атрибутом в классе модели.
  3. Тоже самое, что 2, только не является.
  4. Несколько колонок.

@unclead
Copy link
Owner

unclead commented Aug 26, 2021

Вообще в текущем виде PR меняет довольно сильно логику и это может сломать обратную совместимость учитывая отсутствие нормальных тестов.

@olegbaturin а ты смотрел мой быстрофикс? #355

Дело в том, что давно летает в воздухе мысль все переписать нормально в 3 версии и вот в ней уже можно ломать обратную совместимость сколько душе будет угодно 😄

@olegbaturin
Copy link
Author

Вообще в текущем виде PR меняет довольно сильно логику и это может сломать обратную совместимость учитывая отсутствие нормальных тестов.

Сломается только имя для одной колонки.
Было ClassName['filter']['field'][0]
Стало ClassName['filter'][0]['field']

Могу добавить проверок, чтобы для одной колонки и у модели нет атрибута, вид остался ClassName['filter']['field'][0]. Для моделей без имени класса в имени инпута как бы не работало и так, ломать нечего.

@olegbaturin
Copy link
Author

а ты смотрел мой быстрофикс? #355

Смотрел. Не помню, что не понравилось. Может как раз разное имя для одной и нескольких колонок. Вероятно, что он сейчас и решит баг, если оставить разные имена для одной и нескольких колонок.

@unclead
Copy link
Owner

unclead commented Aug 26, 2021

Сломается только имя для одной колонки.
Было ClassName['filter']['field'][0]
Стало ClassName['filter'][0]['field']

вот такие изменения должны быть между мажорными версиями, т.е. в версии 3 про которую я чуть выше упоминал. И Как раз одно из планируемых изменений это унификация имени поля, чтобы не было этой магии "одна колонка или несколько".

Поэтому я против таких кардинальных изменений в версии 2 и нужен фикс в рамках текущей архитектуры (который на мой взгляд я сделал в #355).

Другой вариант - ты можешь использовать свой форк 😄

@unclead
Copy link
Owner

unclead commented Aug 26, 2021

Вот связанный issue - #295

@unclead
Copy link
Owner

unclead commented Aug 26, 2021

Вообще основная идея 3 версии - убрать всю магию и сделать все максимально линейно. Плюс вынести большинство логики в отдельные классы

@olegbaturin
Copy link
Author

чтобы не было этой магии "одна колонка или несколько"

Одну колонку всё равно придется как сейчас обрабатывать отдельно. В случае когда в опциях нет колонок или когда название атрибута у модели совпадает с назанием единственной колонки (по сути переопределение дефолтной колонки). Для кейсов с моделью и без по классам разделить сразу идея приходит в голову. Слишком много условий иначе получается.

@olegbaturin olegbaturin closed this by deleting the head repository Feb 3, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants