Загружать все больше и больше данных при прокрутке вниз в виджете Kartik Select2
Я работаю над системой управления запасами, с большим количеством продуктов, и клиент хочет отобразить продукты в виджете Select2 точно так же, как виджет kartik, и он хочет представлять данные все больше и больше при прокрутке вниз, доступна ли она или может быть сделано с помощью этого виджета или я должен создать свой собственный? это мой код
<?php
$url = Url::to ( [ 'products-list' ] );
echo Select2::widget ( [
'name' => 'state_10' ,
'options' => [
'id' => 'select_product' ,
'placeholder' => 'Select Product...' ,
'multiple' => false ,
'class' => ''
] ,
'pluginOptions' => [
'allowClear' => true ,
'minimumInputLength' => 1 ,
'ajax' => [
'url' => $url ,
'dataType' => 'json' ,
'data' => new JsExpression ( 'function(params) { return {q:params.term}; }' )
] ,
'escapeMarkup' => new JsExpression ( 'function (markup) { return markup; }' ) ,
'templateResult' => new JsExpression ( 'function(product) { console.log(product);return product.text; }' ) ,
'templateSelection' => new JsExpression ( 'function (subject) { return subject.text; }' ) ,
] ,
] );
?>
и у меня есть это действие в моем контроллере, и все работает хорошо, но мне нужно начать с отображения ряда продуктов в select2, а затем при прокрутке начать получать все больше и больше
действие контроллера:
public function actionProductsList($q = null, $id = null) {
Yii::$app->response->format = Response::FORMAT_JSON;
$out = ['results' => ['id' => '', 'text' => '', 'qtyLeft' => '', 'serialNumbers' => '']];
if (!is_null($q)) {
$query = new Query;
$query->select(['product_id as id', new Expression("CONCAT(product_name,' -- ',product_qty_left) AS text, product_qty_left as qtyLeft, s.serial_number as serialNumbers")])
->from('product')
->join('LEFT JOIN', 'serial_number s', 's.r_product_id = product.product_id')
->where(['like', 'product_name', $q]);
// ->limit(20);
$command = $query->createCommand();
$data = $command->queryAll();
$out['results'] = array_values($data);
} elseif ($id > 0) {
$out['results'] = ['id' => $id, 'text' => AppProduct::find()->where(['product_id' => $id])->one()->product_name];
}
return $out;
}
2 ответа
В соответствии с документацией по использованию нумерации страниц, вы должны указать Select2 добавить все необходимые параметры нумерации страниц в запрос, переопределив ajax.data
установка. Текущая страница для извлечения сохраняется в params.page
имущество.
Так что вам нужно изменить Select2
к следующему
$url = Url::to ( [ 'products-list' ] );
echo Select2::widget ( [
'name' => 'state_10' ,
'options' => [
'id' => 'select_product' ,
'placeholder' => 'Select Product...' ,
'multiple' => false ,
'class' => ''
] ,
'pluginOptions' => [
'allowClear' => true ,
'minimumInputLength' => 1 ,
'ajax' => [
'url' => $url ,
'dataType' => 'json' ,
'data' => new JsExpression ( 'function(params) { return {q:params.term, page:params.page || 1}; }' )
] ,
'escapeMarkup' => new JsExpression ( 'function (markup) { return markup; }' ) ,
'templateResult' => new JsExpression ( 'function(product) { console.log(product);return product.text; }' ) ,
'templateSelection' => new JsExpression ( 'function (subject) { return subject.text; }' ) ,
] ,
] );
Select2 будет ожидать pagination.more
значение в ответе. Значение more должно быть true
или же false
, который сообщает Select2, есть ли еще страницы результатов, доступные для поиска:
{
"results": [
{
"id": 1,
"text": "Option 1"
},
{
"id": 2,
"text": "Option 2"
}
],
"pagination": {
"more": true
}
}
поэтому измените ваш серверный код, чтобы включить $page
параметр и включают в себя limit
а также offset
в вашем запросе. я использую 5 записей в качестве ограничения в настоящее время вы можете изменить его.
public function actionProductsList($page, $q = null , $id = null ) {
$limit=5;
$offset=($page-1)*5;
Yii::$app->response->format = Response::FORMAT_JSON;
$out = [ 'results' => [ 'id' => '' , 'text' => '' , 'qtyLeft' => '' , 'serialNumbers' => '' ] ];
if ( !is_null ( $q ) ) {
$query = new \yii\db\Query;
$query->select ( [ 'product_id as id' , new Expression ( "CONCAT(product_name,' -- ',product_qty_left) AS text, product_qty_left as qtyLeft, s.serial_number as serialNumbers" ) ] )
->from ( 'product' )
->join ( 'LEFT JOIN' , 'serial_number s' , 's.r_product_id = product.product_id' )
->where ( [ 'like' , 'product_name' , $q ] )
->offset ( $offset )
->limit ( $limit );
$command = $query->createCommand ();
$data = $command->queryAll ();
$out['results'] = array_values ( $data );
$out['pagination'] = [ 'more' => !empty($data)?true:false ];
} elseif ( $id > 0 ) {
$out['results'] = [ 'id' => $id , 'text' => AppProduct::find ()->where ( [ 'product_id' => $id ] )->one ()->product_name ];
}
return $out;
}
Update
Было несколько исправлений, которые я нашел в приведенном выше коде и изменил
- Исправить смещение
$offset=($page-1)*5;
вместо того, чтобы использовать$page
лайк->offset($page)
использовать$offset
а не как->offset($offset)
, - Сконфигурируйте больше результатов правильно, чтобы они возвращали значение false, если результатов больше нет, в противном случае он продолжает отправлять вызовы ajax на сервер, даже если результатов больше нет, поэтому измените его на
$out['pagination'] = [ 'more' => !empty($data)?true:false ];
kartik\widgets\Select2 имеет поле "данные", в котором вы можете передать массив товаров из баз данных и отфильтровать список товаров в соответствии. В вашем случае я могу использовать приведенный ниже код для реализации такого сценария, как
echo Select2::widget([
'name' => 'state_10',
'options' => [
'placeholder' => 'Select Product...',
'multiple' => false,
],
'data' => ArrayHelper::map(Product::find()->all(), 'id', function($model){
return "{$model->product_id},{$model->product_name}--{$model->product_qty_left}, {$model->product_qty_left}, {$model->relation2serial->serial_number} ";
});
У меня есть представление, что у вас есть модель продукта по отношению к модели serial_number на случай, если вам понадобятся отношения к этой модели и другим моделям для вашего случая.
Надеюсь помогает!!