Различия

Показаны различия между двумя версиями страницы.

Ссылка на это сравнение

Следующая версия
Предыдущая версия
инвентаризация:dev:forms [2025/04/27 14:49]
admin создано
инвентаризация:dev:forms [2025/05/01 18:18] (текущий)
admin [Placeholders]
Строка 1: Строка 1:
 {{tag>dev Инвентаризация forms}} {{tag>dev Инвентаризация forms}}
 ====== Инвентаризация: DEV: Forms ====== ====== Инвентаризация: DEV: Forms ======
 +
 +==== ActiveField ====
 Поскольку у нас шаблон ввода в форме не стандартный, а  Поскольку у нас шаблон ввода в форме не стандартный, а 
-{Label} с иконкой и {hint} в tooltip, {input}, {error}+{Label} с иконкой и {hint} завернутым в tooltip, {input}, {error} 
 + 
 +Переделываем (наследуем) Activefield (от \yii\bootstrap5\ActiveField) следующим образом 
 +  * методы label и hint не заполняют $this->parts['{label}'] и $this->parts['{hint}'] отрендеренным HTML, а сохраняют текстовую часть в labelText и hintText атрибутах 
 +  * в методе render мы уже формируем $this->parts['{label}'] на основании labelText и hintText. $this->parts['{hint}'] остается пустой 
 +    * на самом деле в \yii\bootstrap5\ActiveField есть метод renderLabel и делаем всю магию там 
 +  * $this->parts['{hint}'] можно заполнить методом classicHint, тогда можно отобразить и классическую подсказку после Input 
 + 
 + 
 +==== Text ==== 
 +Сделал метод для ввода текста ->text($options=[]), который может вызывать 
 +  * textAutoresize 
 +  * dokuwikiEdit 
 +  * mardownEdit
  
-Переделываем (наследуем) Activefield следующим образом +В зависимости от настройки  
-По умолчанию в $this->parts хранятся отрендеренные части для шаблона +<code php> 
-Мы в $this->parts['{hint}'] все равно храним Hint, но используем его в шаблоне, а используем при рендере label +'textFields'=>
-Для этого метод render должен  + 'default'=>'text', 
-  * сначала вызывать $this->hint(), который заполнит $this->parts['{hint}' + 'Aces.ips'=>'text', //IP адреса хранить иначе чем текст нет смысла 
-  уже после вызывать $this->label(), который заполнит $this->parts['{label}']  в котором в тултипе будет $this->parts['{hint}'+ 'Aces.notepad'=>'markdown', 
 + 'Acls.notepad'=>'markdown', 
 + 'Comps.ip'=>'text', 
 + 'Comps.mac'=>'text', 
 + 'Comps.raw_hw'=>'text', 
 + 'Comps.raw_sw'=>'text', 
 + 'Comps.external_links'=>'text', 
 + 'MaintenanceReqs.description'=>'markdown', 
 + 'MaintenanceReqs.links'=>'text', 
 + 'LicTypes.links'=>'text', 
 + 'Networks.notepad'=>'markdown', 
 + ], 
 +</code> 
 +==== Modal Popups ==== 
 +Была следующая проблема: если у формы явно не задан ID, то он (т.к. форма наследуется от виджета) формируется как префикс (w) + индекс (0), поэтому по умолчанию у формы ID = w0. 
 +И если на страницу, в которой уже есть форма, через Popup + Ajax подгрузить еще одну форму, то она соответственно тоже будет w0, т.к. она была первой на подгруженной странице. И тут возникает проблема с инициализацией JavaScript, т.к. к форме прилагается скрипт инициализации, и если формы называются одинаково, то возникает коллизия. 
 +++++ пример скрипта инициализации | 
 +<code javascript> 
 +jQuery('#w0').yiiActiveForm([{ 
 +            "id": "aces-users_ids", 
 +            "name": "users_ids", 
 +            "container": ".field-aces-users_ids", 
 +            "input": "#aces-users_ids", 
 +            "error": ".invalid-feedback", 
 +            "enableAjaxValidation": true 
 +        }, { 
 +            "id": "aces-comps_ids", 
 +            "name": "comps_ids", 
 +            "container": ".field-aces-comps_ids", 
 +            "input": "#aces-comps_ids", 
 +            "error": ".invalid-feedback", 
 +            "enableAjaxValidation": true 
 +        }, { 
 +            "id": "aces-services_ids", 
 +            "name": "services_ids", 
 +            "container": ".field-aces-services_ids", 
 +            "input": "#aces-services_ids", 
 +            "error": ".invalid-feedback", 
 +            "enableAjaxValidation": true 
 +        }, { 
 +            "id": "aces-ips", 
 +            "name": "ips", 
 +            "container": ".field-aces-ips", 
 +            "input": "#aces-ips", 
 +            "error": ".invalid-feedback", 
 +            "enableAjaxValidation": true 
 +        }, { 
 +            "id": "aces-comment", 
 +            "name": "comment", 
 +            "container": ".field-aces-comment", 
 +            "input": "#aces-comment", 
 +            "error": ".invalid-feedback", 
 +            "enableAjaxValidation": true 
 +        }, { 
 +            "id": "aces-name", 
 +            "name": "name", 
 +            "container": ".field-aces-name", 
 +            "input": "#aces-name", 
 +            "error": ".invalid-feedback", 
 +            "enableAjaxValidation": true 
 +        }, { 
 +            "id": "aces-access_types_ids", 
 +            "name": "access_types_ids", 
 +            "container": ".field-aces-access_types_ids", 
 +            "input": "#aces-access_types_ids", 
 +            "error": ".invalid-feedback", 
 +            "enableAjaxValidation": true 
 +        }, { 
 +            "id": "aces-notepad", 
 +            "name": "notepad", 
 +            "container": ".field-aces-notepad", 
 +            "input": "#aces-notepad", 
 +            "error": ".invalid-feedback", 
 +            "enableAjaxValidation": true 
 +        }, { 
 +            "id": "aces-acls_id", 
 +            "name": "acls_id", 
 +            "container": ".field-aces-acls_id", 
 +            "input": "#aces-acls_id", 
 +            "error": ".invalid-feedback", 
 +            "enableAjaxValidation": true 
 +        } 
 +    ], { 
 +    "errorSummary": ".alert.alert-danger", 
 +    "errorCssClass": "is-invalid", 
 +    "successCssClass": "is-valid", 
 +    "validationStateOn": "input", 
 +    "validationUrl": "\/web\/aces\/validate?id=675" 
 +}); 
 +</code> 
 +++++ 
 +во избежание подобных коллизий мы делаем в init по умолчанию id вида className-id-form 
 +Для этого во всех формах желательно указывать модель через конфиг 
 +==== Placeholders ==== 
 +Во-первых у ArmsModel есть метод getAttributePlaceholder($attribute), который возвращает плейсхолдер для поля ввода атрибута. 
 +Если атрибут отмечен как is_inheritable, то возвращает унаследованное значение (либо указанное в inheritablePlaceholder параметре атрибута (может быть и функцией)) 
 +Во вторых в [[#ActiveField]] все методы для вывода инпутов переопределены для подгрузки плейсхолдеров 
 +В третьих в форме по умолчанию включена Ajax валидация, которая в ArmsBaseController тоже переопределена и к данным валидации добавляет значения плейсхолдеров для валидируемого набора значений модели. Зачем? Меняем родителя - меняются унаследованные значения, которые видно в плейсхолдерах 
 +В четвертых, чтобы обрабатывать передаваемые плейсхолдеры к форме прикрепляется обработчик события OnAjaxComplete
  
 +==== Валидация ====
 +По умолчанию формы включают ajax валидацию, но чтобы сгенерировать url валидации по умолчанию (который обслуживается через ArmsBaseController) нужно указывать модель в конфигурацию формы
  • инвентаризация/dev/forms.1745765399.txt.gz
  • Последнее изменение: 2025/04/27 14:49
  • admin