Заполнение поля данными
Заполнение поля данными
Есть Виджет
Если выводить всё дерево сразу и без ajax, то после сохранения выведутся все поля в данном виджете. (работает хорошо, но нужна ajax подгрузка).
Если выводить первый уровень дерева и с ajax подгрузкой, то после сохранения и обновления страницы покажутся данные из верхнего уровня, а остальные уровни не покажутся, но из модели передаются все id записей, которые должны отобразиться.
Может кто подскажет, как отредактировать виджет, чтобы выводился весь список данных и работало с ajax подгрузкой.
Первоначальное наполнение виджета идет выборкой верхнего уровня дерева.
Если выводить всё дерево сразу и без ajax, то после сохранения выведутся все поля в данном виджете. (работает хорошо, но нужна ajax подгрузка).
Если выводить первый уровень дерева и с ajax подгрузкой, то после сохранения и обновления страницы покажутся данные из верхнего уровня, а остальные уровни не покажутся, но из модели передаются все id записей, которые должны отобразиться.
Может кто подскажет, как отредактировать виджет, чтобы выводился весь список данных и работало с ajax подгрузкой.
Первоначальное наполнение виджета идет выборкой верхнего уровня дерева.
-
- Сообщения: 910
- Зарегистрирован: 2019.08.13, 01:49
Re: Заполнение поля данными
Поставил ради интереса, нормально работает и с аджаксом и без.
Только fontawesome 4.7 добавить и подключить надо, скорее всего вы этого не сделали.
В composer.json добавьте "rmrevin/yii2-fontawesome": "~2.17" и обновите, потом в нужной вьюхе зарегайте \rmrevin\yii\fontawesome\AssetBundle::register($this);
Только fontawesome 4.7 добавить и подключить надо, скорее всего вы этого не сделали.
В composer.json добавьте "rmrevin/yii2-fontawesome": "~2.17" и обновите, потом в нужной вьюхе зарегайте \rmrevin\yii\fontawesome\AssetBundle::register($this);
Re: Заполнение поля данными
У меня PRO версия fontawesome и я подправил её в виджете. У меня всё разворачивается и всё добавляется. Сейчас покажу скриншоты, что нужно в данном вопросе.yiiliveext писал(а): ↑2019.12.18, 13:34 Поставил ради интереса, нормально работает и с аджаксом и без.
Только fontawesome 4.7 добавить и подключить надо, скорее всего вы этого не сделали.
В composer.json добавьте "rmrevin/yii2-fontawesome": "~2.17" и обновите, потом в нужной вьюхе зарегайте \rmrevin\yii\fontawesome\AssetBundle::register($this);
1. Выбор элементов http://prntscr.com/qcdotf
2. Вывод элементов, которые были сохранены в БД http://prntscr.com/qcdp7d
3. После сохранения виджет показывает вот что http://prntscr.com/qcdpe2 (то что выбраны все элементы первого уровня это нормально, и при развертывании первого уровня должны быть выбраны и элементы из первого скриншота, но не прописываются они в скрытых полях и поэтому пустые).
-
- Сообщения: 910
- Зарегистрирован: 2019.08.13, 01:49
Re: Заполнение поля данными
Ну так добавьте их в js, там где подгрузка ajax-ом идет.unknownby писал(а): ↑2019.12.18, 13:46
3. После сохранения виджет показывает вот что http://prntscr.com/qcdpe2 (то что выбраны все элементы первого уровня это нормально, и при развертывании первого уровня должны быть выбраны и элементы из первого скриншота, но не прописываются они в скрытых полях и поэтому пустые).
Re: Заполнение поля данными
Я проверял, если без подгрузки ajax-ом сразу вывести весь справочник, то он показывает их как нужно, если работает ajax подгрузка, то внутренние элементы оказываются еще не известными, т.к. в списке их нет. Ajax подгрузка подгружает дочерние элементы в зависимости от parent_id, который выбран.
Код: Выделить всё
public function actionGetchilds() {
$node_id = \Yii::$app->request->post('node_id');
if (!is_numeric($node_id)) {
$model = MyClass::find()
->andWhere(['parent_id' => 0])
->orderBy(['id' => SORT_ASC, 'name' => SORT_ASC])->all();
} else {
$model = MyClass::find()
->where(['parent_id' => $node_id ])
->orderBy(['id' => SORT_ASC, 'name' => SORT_ASC])->all();
}
$childsList = [];
if ($model !== null && is_array($model) && count($model) > 0) {
foreach($model as $item) {
$child = MyClass::find()->where(['parent_id' => $item->id])->all();
if(0 < count($child)){
$childsList[] = ['id' => $item->id, 'label' => $item->name, 'items' => []];
} else {
$childsList[] = ['id' => $item->id, 'label' => $item->name];
}
}
}
return json_encode($childsList);
}
Т.е. если выбраны три первые ветки и из первой ветки выбрано три элемента, то нужно первоначально загружать для данной записи все элементы, где parent_id = 0 и дополнительно присоединять запрос, который найдет вложенность в первую ветку всех элементов.
Тогда выдаст весь верхний уровень + второй уровень первого элемента.
Re: Заполнение поля данными
Сейчас выводит хорошо, но нужна рекурсия и чтобы правильно всё же работало.
Вот так сейчас заполняется справочник элементами для первого и второго уровня
Вот так сейчас заполняется справочник элементами для первого и второго уровня
Код: Выделить всё
//наполнение дерева вначале первым уровнем, дальше работает наполнение дочерних элементов, если передается $model (это данные из модели), которые были сохранены в БД.
public function findTree($model = 0){
$tree = [];
$items = MyClass::find()->where(['parent_id' => 0])->all();
foreach($items as $v){
$treeObj = [];
if($model != 0){
//тут надо как-то рекурсией наполнить, чтобы foreach выбирался пока не будет последний элемент из дерева
//еще пока не придумал
foreach($model as $val){
if($v->id == $val->parent_id){
$treeObj = self::childNodes($v->id);
}
}
}
$tree[] = ['id' => $v->id, 'label' => $v->name, 'items' => $treeObj];
}
return $tree;
}
//получение дочерних элементов
private function childNodes($parentId){
$treeObj = [];
$child = MyClass::find()->where(['parent_id' => $parentId])->all();
foreach($child as $v){
$treeObj[] = ['id' => $v->id, 'label' => $v->name, 'items' => []];
}
return $treeObj;
}
-
- Сообщения: 910
- Зарегистрирован: 2019.08.13, 01:49
Re: Заполнение поля данными
Нет, там надо в начале добавить соответствующие hidden input и <li>, котрорых нет в $items и при клике делать проверку на существование.unknownby писал(а): ↑2019.12.18, 16:11 У меня предположение, что нужно подгружать все ветки, где выбраны элементы. Но не в ajax подгрузке, а в начальной загрузке элементами для виджета. Чтобы он их увидел и отобразил в поле, типо сделана ajax подгрузка без нажатия на "+" в dropdown. Пока что работаю в эту сторону.
Т.е. если выбраны три первые ветки и из первой ветки выбрано три элемента, то нужно первоначально загружать для данной записи все элементы, где parent_id = 0 и дополнительно присоединять запрос, который найдет вложенность в первую ветку всех элементов.
Тогда выдаст весь верхний уровень + второй уровень первого элемента.
Это кривой виджет, там надо рефакторить js и исправлять ошибки, сейчас он не будет правильно работать даже без аджакса.
-
- Сообщения: 910
- Зарегистрирован: 2019.08.13, 01:49
Re: Заполнение поля данными
Порефакторил немного код и дописал загрузку аджаксом выбранных, довольно рабочий вариант получился. Еще часика три потратить бы на доработку, и получится более-менее толковый виджет.
https://i.imgur.com/bgXmQvR.gifv
https://i.imgur.com/bgXmQvR.gifv
Re: Заполнение поля данными
То что нужно. А само решение можно?yiiliveext писал(а): ↑2019.12.18, 23:04 Порефакторил немного код и дописал загрузку аджаксом выбранных, довольно рабочий вариант получился. Еще часика три потратить бы на доработку, и получится более-менее толковый виджет.
https://i.imgur.com/bgXmQvR.gifv
Re: Заполнение поля данными
Когда у категории снимаешь флажок у ее подкатегорий флажок не снимается, этот момент не ожидаемый.
Yii2 universal module sceleton - for basic and advanced templates
Re: Заполнение поля данными
В моем случае такое подходит Если расценивать элементы дерева как отличные друг от друга (хоть и находятся в иерархии), а если как категории/подкатегории тогда нужно было бы снимать флажок (т.к. взаимосвязанные данные выходят)
-
- Сообщения: 910
- Зарегистрирован: 2019.08.13, 01:49
Re: Заполнение поля данными
Временный репо https://github.com/yiiliveext/yii2-tree-dropdown
Как склонируете - маякнете, я удалю.
Вам нужно только заменить файл view.php и в модели реализовать метод getItemLabel($id), который будет возвращать наименование по айди.
Ветки подгружаете по уровням, то есть прилетел айди по аджаксу, делаете SELECT * FROM mytable WHERE parent_id = :id и потом в цикле перебираете полученных детей и проверяете в них наличие собственных детей SELECT * FROM mytable WHERE parent_id = :id LIMIT 1, если есть, то добавляете 'items' => []. По наличию ключа items скрипт определяет необходимость добавления иконки раскрытия ветки (у листьев я ее вообще убрал).
Re: Заполнение поля данными
Круто, спасибо. Скачал.yiiliveext писал(а): ↑2019.12.19, 10:26 Вам нужно только заменить файл view.php и в модели реализовать метод getItemlabel($id), который будет возвращать наименование по айди.
Ветки подгружаете по уровням, то есть прилетел айди по аджаксу, делаете SELECT * FROM mytable WHERE parent_id = :id и потом в цикле перебираете полученных детей и проверяете в них наличие собственных детей SELECT * FROM mytable WHERE parent_id = :id LIMIT 1, если есть, то добавляете 'items' => []. По наличию ключа items скрипт определяет необходимость добавления иконки раскрытия ветки (у листьев я ее вообще убрал).
Я когда подгружаю детей ajax-ом, то делаю запрос с выборкой всего, только без лимита (пока что, т.к. там всего до 10 записей работало быстро), но думаю стоит добавить. Добавление иконки раскрытия переделал, там было если не определено значение, то по-умолчанию минус писало, подправил условие и теперь если не определено значение $items, то пустоту прописывает.
Буду сейчас внедрять правки
-
- Сообщения: 910
- Зарегистрирован: 2019.08.13, 01:49
Re: Заполнение поля данными
Это уже переделано в моем варианте, я написал выше, просто замените view.php
-
- Сообщения: 910
- Зарегистрирован: 2019.08.13, 01:49
Re: Заполнение поля данными
Лимит там только у запроса по детям детей, чтобы добавить пустой items, если у них есть дети, иначе не будет ветка раскрываться. Сами дети прилетевшего айди выбираются без лимита
-
- Сообщения: 910
- Зарегистрирован: 2019.08.13, 01:49
Re: Заполнение поля данными
Внес пару исправлений, репо пока не удалял
Re: Заполнение поля данными
Заменил, всё шикарно. Нашел мини баг. Если убрать все сохранные элементы и нажать сохранить. При этом в контроллере при обновлении просто рендер страницы.yiiliveext писал(а): ↑2019.12.19, 10:40 Это уже переделано в моем варианте, я написал выше, просто замените view.php
Код: Выделить всё
public function actionUpdate($id)
{
$model = $this->findModel($id);
if ($model->load(\Yii::$app->getRequest()->post()) && $model->save()) {
\Yii::$app->session->setFlash($this->flashClass, \Yii::t('main', 'flash.updateSuccess'));
}
return $this->render('update', [
'model' => $model,
]);
}
-
- Сообщения: 910
- Зарегистрирован: 2019.08.13, 01:49
Re: Заполнение поля данными
Гляньте последние коммиты или скачайте заново view.php, я там исправил. Я просто на эмулированных данных тестил, реальные модели не подключал, так что пишите, если что не так
Re: Заполнение поля данными
Я заменил уже новым файлом view.phpyiiliveext писал(а): ↑2019.12.19, 12:03 Гляньте последние коммиты или скачайте заново view.php, я там исправил. Я просто на эмулированных данных тестил, реальные модели не подключал, так что пишите, если что не так
Если сохранить пустой список, то дальше не открывается список, нужна перезагрузка страницы.
-
- Сообщения: 910
- Зарегистрирован: 2019.08.13, 01:49
Re: Заполнение поля данными
Там два коммита было, последний решает эту проблему.
А если перезагрузить страницу с пустым списком в поле модели, то работает?
У вас там не pjax часом используется?