Страница 2 из 5
Re: Сохранение значений
Добавлено: 2020.01.09, 10:57
yiiliveext
unknownby писал(а): ↑2020.01.09, 09:52
yiiliveext писал(а): ↑2020.01.09, 09:42
Все не надо было, только функционал перезагрузки ajax-ом.
Сделаю потом снова рендер файла, а JS будет в основном представлении.
Не надо делать весь js в основном представлении.
Разрабатывайте с той точки зрения, чтобы фильтры и смену представления можно было вынести в отдельные независимые виджеты.
Виджет при этот сам по себе не занимается перезагрузкой контента страницы. Он только меняет состояние и уведомляет основную страницу о необходимости перезагрузки, это можно сделать либо через вызов функции основной страницы, либо через событие. В простейшем случае состояние можно хранить в виде глобальной переменной-объекта, которая потом в основном представлении будет собираться и отправляться в виде data в ajax-запросе.
Примерно так.
В представлении фильтра
Код: Выделить всё
$js = "
var checkboxes = [];
$('input[type=checkbox]').on('click', function(){
var selection = $(this).val();
var id = $(this)[0].id;
var check = $(this)[0].checked;
var value = id.split('-');
var data;
if(check){
checkboxes.push(selection + '-' + value[2]);
} else {
checkboxes.splice(checkboxes.indexOf(selection + '-' + value[2]), 1);
}
pageState['checkboxes'] = '".$searchModelName."[options]=' + checkboxes;
reloadContent();
});";
В представлении смены представления
Код: Выделить всё
$js .= "
$('.item-view-select > span').on('click', function(){
pageState['itemView'] = 'itemViews=' + $(this).data('view_name');
reloadContent();
});
";
В основном представлении.
Код: Выделить всё
$js="
var pageState = {};
function reloadContent() {
var data = '';
$.each(pageState, function(key, value) {
data += '&' + value;
});
$.ajax({
type: 'POST',
url: '".$model->productscategory_url."',
data: data.substr(1),
success: function(result){
$('#lestview-products').html(result);
},
});
}";
Re: Сохранение значений
Добавлено: 2020.01.09, 11:20
unknownby
yiiliveext писал(а): ↑2020.01.09, 10:57
Не надо делать весь js в основном представлении.
Разрабатывайте с той точки зрения, чтобы фильтры и смену представления можно было вынести в отдельные независимые виджеты.
Виджет при этот сам по себе не занимается перезагрузкой контента страницы. Он только меняет состояние и уведомляет основную страницу о необходимости перезагрузки, это можно сделать либо через вызов функции основной страницы, либо через событие. В простейшем случае состояние можно хранить в виде глобальной переменной-объекта, которая потом в основном представлении будет собираться и отправляться в виде data в ajax-запросе.
Фильтры будут в отдельном представлении, а смена представлений маленький блок и по сути можно не выделять в независимый виджет, но если напихать в него еще функционал, тогда да. Выделю лучше сразу в отдельное представление, с залогом на будущую доработку, мб и напихаю еще полезностей разных в него.
Собирание в одну переменную и вызов функции, которая будет в основном представлении, то что доктор прописал
Буду реализовывать вечером, благодарю
Re: Сохранение значений
Добавлено: 2020.01.09, 12:56
yiiliveext
unknownby писал(а): ↑2020.01.09, 11:20
а смена представлений маленький блок и по сути можно не выделять в независимый виджет, но если напихать в него еще функционал, тогда да. Выделю лучше сразу в отдельное представление, с залогом на будущую доработку, мб и напихаю еще полезностей разных в него.
Обычно туда еще входит сортировка. Иногда селект с деревом категорий для быстрого перехода.
Получается такой себе PageListToolbar виджет.
Re: Сохранение значений
Добавлено: 2020.01.11, 18:50
unknownby
yiiliveext писал(а): ↑2020.01.09, 12:56
Обычно туда еще входит сортировка. Иногда селект с деревом категорий для быстрого перехода.
Получается такой себе PageListToolbar виджет.
Поработал с бесконечной подгрузкой товаров через ajax.
Тут
InfiniteScrollPager мое представление с ListView.
Есть проблемы о которых ранее вы говорили, о POST и GET. Сама подгрузка товаров в InfiniteScrollPager осуществляется ajax-ом через GET запрос. Придется видимо переделывать, чтобы при фильтрации передавались параметры GET-ом и прописывались в URL страницы. Или может есть какие-нибудь идеи по тому, чтобы работало всё вместе? Чтобы работала подгрузка ajax-ом через GET (InfiniteScrollPager) при этом работала фильтрация при помощи POST, может сохранять в сессию значения и потом выводить сессию в dataProvider?
Взяв за пример
эту реализацию
В контроллере есть isAjax и можно вставить костыль, но не правильная разработка таким образом
Код: Выделить всё
if(\Yii::$app->request->isAjax && (!\Yii::$app->request->getQueryParam('per-page') || !\Yii::$app->request->getQueryParam('page'))){
С костылем все равно нужна будет реализация другая.
Т.е. сделать так, чтобы InfiniteScrollPager в контроллере проходил условие, где добавляются значения в сессию, а просто дальше шел по контроллеру и выводил данные которые нужны вместе с данными по фильтрам
Re: Сохранение значений
Добавлено: 2020.01.11, 23:18
yiiliveext
unknownby писал(а): ↑2020.01.11, 18:50
yiiliveext писал(а): ↑2020.01.09, 12:56
Обычно туда еще входит сортировка. Иногда селект с деревом категорий для быстрого перехода.
Получается такой себе PageListToolbar виджет.
Придется видимо переделывать, чтобы при фильтрации передавались параметры GET-ом и прописывались в URL страницы.
Именно так и надо.
Представьте ситуацию, пользователь зашел в категорию в которой десяток-другой фильтров и потратил минут десять на фильтрацию, а потом добавил товар в корзину и перешел в нее. Потом передумал и нажал в браузере кнопку "Назад". Что он получит в вашем случае, когда вы передаете POST-ом? Правильно, хреном по всей морде. И в итоге плюнет и уйдет. А вот с GET-ом такой фигни не будет, так же как и при перезагрузке страницы с выставленными фильтрами, плюс на фильтры есть ссылка. Или вы никогда не сталкивались с необходимостью скинуть ссылку на отфильтрованный набор товаров?
Если вы все реализовали из того, что я раньше писал, то там совсем немного переделать, буквально несколько строчек добавить/поменять.
Re: Сохранение значений
Добавлено: 2020.01.12, 03:09
unknownby
yiiliveext писал(а): ↑2020.01.11, 23:18
Если вы все реализовали из того, что я раньше писал, то там совсем немного переделать, буквально несколько строчек добавить/поменять.
Всё, кроме контроллера реализовал.
Re: Сохранение значений
Добавлено: 2020.01.12, 12:20
yiiliveext
unknownby писал(а): ↑2020.01.12, 03:09
Всё, кроме контроллера реализовал.
При передаче GET-ом контроллер становится совсем крохотных размеров.
Да и на фронте код можно сократить. Например, заменить вызов многострочного метода ajax() на однострочный load().
А добавится только pushState() и обработчик события popstate.
Re: Сохранение значений
Добавлено: 2020.01.12, 16:31
unknownby
yiiliveext писал(а): ↑2020.01.12, 12:20
unknownby писал(а): ↑2020.01.12, 03:09
Всё, кроме контроллера реализовал.
При передаче GET-ом контроллер становится совсем крохотных размеров.
Да и на фронте код можно сократить. Например, заменить вызов многострочного метода ajax() на однострочный load().
А добавится только pushState() и обработчик события popstate.
Я погугли, почитал, посмотрел разные примеры.
С этим точно нужна помощь. Я в этом тёмный лес.
Re: Сохранение значений
Добавлено: 2020.01.12, 17:21
yiiliveext
Re: Сохранение значений
Добавлено: 2020.01.13, 22:33
unknownby
Вот что наваял, но есть минимальные трудности с подгрузкой данных при помощи InfiniteScrollPager
Сохраняются состояния, выбираются товары по фильтрам, но при сработке бесконечной загрузке, в GET передается не полностью вся строка с моими данными, а добавляется номер страницы и количество товаров, которое я указал в search-е
Контроллер
Код: Выделить всё
public function actionProducts($url)
{
$model = $this->findModelCategory($url);
$searchModel = new ProductsSearch;
$settings = Settings::findOne(Settings::SETTING_DEFAULT);
$session = Yii::$app->session;
$pageState = $session->has('pageState') ? $session->get('pageState') : ['itemViews' => '_product_item'];
if(\Yii::$app->request->isAjax){
$pageState = array_merge($pageState, \Yii::$app->getRequest()->get());
$session->set('pageState', $pageState);
$dataProvider = $searchModel->search($pageState, $model->productscategory_id);
}
$dataProvider = $searchModel->search(\Yii::$app->getRequest()->get(), $model->productscategory_id);
return $this->render('products', [
'model' => $model,
'searchModel' => $searchModel,
'dataProvider' => $dataProvider,
'settings' => $settings,
'itemView' => $pageState['itemViews'],
]);
}
В представлении поменял
Код: Выделить всё
$js = "
var pageState = {};
var listview = $('#listview-products');
function reloadContent() {
var data = '';
$.each(pageState, function(key, value) {
data += '&' + value;
});
var state = data.substr(1);
window.history.pushState(state, '".$model->productscategory_name."', '?' + state);
loadPage('?' + state);
}
function loadPage(url){
listview.load(url + ' #listview-products > *');
}
window.onpopstate = function(event) {
var State = window.history.state;
loadPage('?' + State);
};
";
Куда двигаться?
Re: Сохранение значений
Добавлено: 2020.01.14, 10:23
yiiliveext
Для начала исправить скрипт на фронте, он не совсем корректно работает.
Re: Сохранение значений
Добавлено: 2020.01.14, 11:21
unknownby
yiiliveext писал(а): ↑2020.01.14, 10:23
Для начала исправить скрипт на фронте, он не совсем корректно работает.
Почему не корректно?
При нажатии на чекбоксы или вид представления он передает в
pushState (состояние/title/дополнение к моему урлу)
В
state хранится, например,
ProductsSearch[options]=1-1,2-1 или со сменой представления
ProductsSearch[options]=1-1,2-1&itemViews=_product_item и присоединяю к URL при помощи
"?"
loadPage - загрузка страницы по новому URL
При каждом нажатии срабатывает reloadContent, сохраняется состояние и дальше загружается страница.
Код: Выделить всё
function reloadContent() {
var data = '';
$.each(pageState, function(key, value) {
data += '&' + value;
});
var state = data.substr(1);
window.history.pushState(state, '".$model->productscategory_name."', '?' + state);
loadPage('?' + state);
}
Функция загрузки по урлу
Код: Выделить всё
function loadPage(url){
listview.load(url + ' #listview-products > *');
}
Загрузка страниц при переходе назад/вперед в браузере, если человек будет возвращаться ранее выбранным выборкам.
Код: Выделить всё
window.onpopstate = function(event) {
var State = window.history.state;
loadPage('?' + State);
};
Можно конечно переделать загрузку по урлу таким образом, если в этом вопрос
Код: Выделить всё
function loadPage(url){
listview.load('?' + url + ' #listview-products > *');
}
И вызов тогда загрузки сведется к такому виду
Re: Сохранение значений
Добавлено: 2020.01.14, 11:27
yiiliveext
unknownby писал(а): ↑2020.01.14, 11:21
yiiliveext писал(а): ↑2020.01.14, 10:23
Для начала исправить скрипт на фронте, он не совсем корректно работает.
Почему не корректно?
Ссылка должна быть от корня, а не только квери.
/category?filters=1-2,3-5&view=product-list а не ?filters=1-2,3-5$view=product-list
Re: Сохранение значений
Добавлено: 2020.01.14, 11:54
unknownby
yiiliveext писал(а): ↑2020.01.14, 11:27
Ссылка должна быть от корня, а не только квери.
/category?filters=1-2,3-5&view=product-list а не ?filters=1-2,3-5$view=product-list
Так если оно так работает, зачем передавать от корня?
От корня будет /products/kategoria-11?filters=1-2,3-5&view=product-list
Будет название action и наименование url , дальше фильтры
Re: Сохранение значений
Добавлено: 2020.01.14, 12:10
yiiliveext
И контроллер тоже неправильный. У вас dataProvider всегда перезаписывается.
Re: Сохранение значений
Добавлено: 2020.01.14, 12:38
unknownby
yiiliveext писал(а): ↑2020.01.14, 12:10
И контроллер тоже неправильный. У вас dataProvider всегда перезаписывается.
Вот с ним знаю, что проблемы
Но пока не понял где и что дописать.
Тут начальная загрузка страницы
Код: Выделить всё
$model = $this->findModelCategory($url);
$searchModel = new ProductsSearch;
$settings = Settings::findOne(Settings::SETTING_DEFAULT);
$session = Yii::$app->session;
$pageState = $session->has('pageState') ? $session->get('pageState') : ['itemViews' => '_product_item'];
//убран ajax
$dataProvider = $searchModel->search(\Yii::$app->getRequest()->get(), $model->productscategory_id);
return $this->render('products', [
'model' => $model,
'searchModel' => $searchModel,
'dataProvider' => $dataProvider,
'settings' => $settings,
'itemView' => $pageState['itemViews'],
]);
А когда сработал ajax, то сделать merge, переопределить сессию с новыми данными и в search помещаем pageState.
Код: Выделить всё
if(\Yii::$app->request->isAjax){
$pageState = array_merge($pageState, \Yii::$app->getRequest()->get());
$session->set('pageState', $pageState);
$dataProvider = $searchModel->search($pageState, $model->productscategory_id);
}
Вопрос вот в чем.
Когда работает InfiniteScrollPager он не объединяет свои значения с теми, что были указаны в сессии. Он дописывает к URL ?page=2&per-page=4
Передает при этом Query String Parameters page: 2 per-page: 4
Как сделать, чтоб объединил мои параметры из get() которые отправляются как данные с формы Form Data с параметрами, которые приходят из Query String Parameters
Думал о merge с getQueryParams(), что-то такого. Но по сути оба URL формата GET и должны были объединяться в любом случае
Re: Сохранение значений
Добавлено: 2020.01.14, 13:18
yiiliveext
Если переделаете ссылки от корня, как я вам рекомендовал, то будет так
Код: Выделить всё
function loadPage(url) {
listview.load(url + ' #listview-products > *', function() {
try {
$('ul.pagination > li.next a:first').attr('href', url + '&' + $('ul.pagination > li.next a:first').attr('href').split('?').pop());
} catch (e) {}
});
}
или так
Код: Выделить всё
function loadPage(url) {
listview.load(url + ' #listview-products > *', function() {
var next = $('ul.pagination > li.next a:first');
if (next) {
next.attr('href', url + '&' + next.attr('href').split('?').pop());
}
});
}
В котроллере не надо мержить весь GET и сохранять в состояние.
Re: Сохранение значений
Добавлено: 2020.01.14, 13:28
yiiliveext
Код: Выделить всё
$model = $this->findModelCategory($url);
$searchModel = new ProductsSearch;
$settings = Settings::findOne(Settings::SETTING_DEFAULT);
$session = Yii::$app->session;
if (\Yii::$app->getRequest()->get('itemViews')) {
$itemViews = \Yii::$app->getRequest()->get('itemViews');
$session->set('itemViews', $itemViews);
} else {
$itemViews = $session->has('itemViews') ? $session->get('itemViews') : '_product_item';
}
$dataProvider = $searchModel->search(\Yii::$app->getRequest()->get(), $model->productscategory_id);
return $this->render('products', [
'model' => $model,
'searchModel' => $searchModel,
'dataProvider' => $dataProvider,
'settings' => $settings,
'itemView' => $itemViews,
]);
Re: Сохранение значений
Добавлено: 2020.01.14, 13:56
unknownby
yiiliveext писал(а): ↑2020.01.14, 13:18
Если переделаете ссылки от корня, как я вам рекомендовал, то будет так
Код: Выделить всё
function loadPage(url) {
listview.load(url + ' #listview-products > *', function() {
try {
$('ul.pagination > li.next a:first').attr('href', url + '&' + $('ul.pagination > li.next a:first').attr('href').split('?').pop());
} catch (e) {}
});
}
или так
Код: Выделить всё
function loadPage(url) {
listview.load(url + ' #listview-products > *', function() {
var next = $('ul.pagination > li.next a:first');
if (next) {
next.attr('href', url + '&' + next.attr('href').split('?').pop());
}
});
}
В котроллере не надо мержить весь GET и сохранять в состояние.
Если так сделать, подойдет для функции?
Не могу проверить, только вечером
В pushState первую переменную передавать целый url или всё же оставить state? Там же состояние страницы
Код: Выделить всё
var state = data.substr(1);
var url = '/products/'".$model->productscategory_url."'?' + state;
window.history.pushState(state, '".$model->productscategory_name."', url);
loadPage(url);
А контроллер всё уменьшается и уменьшается
Я бы эту конструкцию
Код: Выделить всё
if (\Yii::$app->getRequest()->get('itemViews')) {
$itemViews = \Yii::$app->getRequest()->get('itemViews');
$session->set('itemViews', $itemViews);
} else {
$itemViews = $session->has('itemViews') ? $session->get('itemViews') : '_product_item';
}
Сделал бы так
Код: Выделить всё
$itemViews = $session->has('itemViews') ? $session->get('itemViews') : '_product_item';
if (\Yii::$app->getRequest()->get('itemViews')) {
$itemViews = \Yii::$app->getRequest()->get('itemViews');
$session->set('itemViews', $itemViews);
}
$itemViews всё равно перезапишется, если был get('itemViews')
Re: Сохранение значений
Добавлено: 2020.01.14, 14:29
yiiliveext
unknownby писал(а): ↑2020.01.14, 13:56
Если так сделать, подойдет для функции?
Что значит подойдет? Infinit-scroll по умолчанию работает со ссылкой $('ul.pagination > li.next a:first').attr('href'), берет ее загружает по ней данные ajax-ом, фильтрует по элементу с itemsCssClass и добавляет в элемент с itemsCssClass вашей страницы, обновляете ссылку next из полученных данных. Только скорее всего страницу всегда вторую надо ставить после загрузки фильтров, надо подумать и немного подправить эту функцию.
В pushState первую переменную передавать целый url или всё же оставить state? Там же состояние страницы
Целый
Я бы эту конструкцию
Сделал бы так
$itemViews всё равно перезапишется, если был get('itemViews')
Можно и так, но всегда будет запрос к сессиям, даже если он не нужен.
А сессии могут находиться в бд или редисе на отдельном сервере.
Если лишний запрос по сети вас устраивает, то можно и так.