Yii2:如何在 AJAX-based Kartik 的 Select2 中使用选项组
Yii2: How to use option groups with AJAX-based Kartik's Select2
目前,我有一个表单字段来呈现一个静态下拉列表,其中包含基于 Kartik 的 Select2 的选项组。使用以下内容填充数据:
public function getBibliographyList()
{
return ArrayHelper::map($this->find()->select(['id','title','author'])
->orderBy('author','title')->all(), 'id', 'title', 'author');
}
以便标题显示在各自的作者选项组下。
现在我想修改表格以利用 AJAX,所以我以 Krajee Demo Site for Select2 中的示例进行了如下修改:
------ 视图 ----------
<?= $form->field($model, 'orig_id')->widget(Select2::classname(), [
'options' => ['placeholder' => Yii::t('app', 'Select a title...)],
'pluginOptions' => [
'allowClear' => true,
'minimumInputLength' => 3,
'language' => Yii::$app->language,
'theme' => 'krajee',
'ajax' => [
'url' => \yii\helpers\Url::to(['search-doc']),
'dataType' => 'json',
'data' => new JsExpression('function (params) { return {q:params.term}; }'),
],
'errorLoading' => new JsExpression("function () { return '".Yii::t('app', 'Waiting for data...')."'; }"),
'escapeMarkup' => new JsExpression("function (markup) { return markup; }"),
'templateResult' => new JsExpression("function (bibliography) { return bibliography.title; }"),
'templateSelection' => new JsExpression("function (bibliography) { return bibliography.title; }"),
],
]) ?>
--------控制器------------
public function actionSearchDoc($q = null)
{
Yii::$app->response->format = \yii\web\Response::FORMAT_JSON;
$out = ['id' => '', 'title' => '', 'author' => ''];
if ($q) {
$query = new yii\db\Query;
$query->select('id, title, author')
->from('bibliography')
->where(['like', 'title', $q])
->orWhere(['like', 'author', $q])
->limit(50);
$command = $query->createCommand();
$data = $command->queryAll();
$out = array_values($data);
}
return \yii\helpers\ArrayHelper::map($out, 'id', 'title', 'author');
}
根据 Kartik 的 Select2 docs,当 optgroups 存在时,ArrayHelper::map 是可行的方法,但我无法解决这个问题,因为结果下拉列表总是空的。这是来自 ArrayHelper::map:
的示例 JSON 字符串
{"results":{"Author1":{"4":"DocumentFoo1","121":"DocumentFoo2","219":"DocumentFoo3","197":"DocumentFoo4","198":"DocumentFoo5","2":"DocumentFoo6","273":"DocumentFoo7"},"Author2":{"68":"DocumentThee1"}}}
有什么想法吗?
这是我自己想出来的。首先,我们必须关心需要的 JSON 字符串以提供基于 AJAX 的 Select2,它必须像这样 (注意特殊关键字 results
、id
、text
和 children
要求基于 AJAX 的 Select2 构建 optgroups):
Array
(
[results] => Array
(
[0] => Array
(
[text] => "author1"
[children] => Array
(
[0] => Array
(
[id] => "id1"
[text] => "title1"
)
[1] => Array
(
[id] => "id2"
[text] => "title2"
)
)
)
[1] => Array
(
[text] => "author2"
[children] => Array
(
[0] => Array
(
[id] => "id3"
[text] => "title3"
)
)
)
)
)
然而,四参数ArrayHelper::map
输出如下:
Array
(
[author1] => Array
(
[id1] => "title1"
[id2] => "title2"
)
[author2] => Array
(
[id3] => "title3"
)
)
所以我们必须重新排列内容并合并那些特殊关键字。因此,正确的控制器操作应该是这样的:
public function actionSearchDoc($q = null)
{
// JSON format result.
Yii::$app->response->format = \yii\web\Response::FORMAT_JSON;
$out['results'] = '';
if ($q) {
$query = Bibliography::find()->select(['id', 'title', 'author'])
->where(['like', 'title', $q])
->orWhere(['like', 'author', $q])
->all();
// Group titles by author.
$authorArray = ArrayHelper::map($query, 'id', 'title', 'author');
// Previous array lacks keywords needed to use optgroups
// in AJAX-based Select2: 'results', 'id', 'text', 'children'.
// Let's insert them.
$results = [];
foreach ($authorArray as $author => $docArray) {
$docs = [];
foreach ($docArray as $id => $title) {
$docs[] = ['id' => $id, 'text' => $title];
}
$results[] = ['text' => $author, 'children' => $docs];
}
$out['results'] = $results;
}
return $out;
}
所以,就是这样。希望对你有帮助。
目前,我有一个表单字段来呈现一个静态下拉列表,其中包含基于 Kartik 的 Select2 的选项组。使用以下内容填充数据:
public function getBibliographyList()
{
return ArrayHelper::map($this->find()->select(['id','title','author'])
->orderBy('author','title')->all(), 'id', 'title', 'author');
}
以便标题显示在各自的作者选项组下。
现在我想修改表格以利用 AJAX,所以我以 Krajee Demo Site for Select2 中的示例进行了如下修改:
------ 视图 ----------
<?= $form->field($model, 'orig_id')->widget(Select2::classname(), [
'options' => ['placeholder' => Yii::t('app', 'Select a title...)],
'pluginOptions' => [
'allowClear' => true,
'minimumInputLength' => 3,
'language' => Yii::$app->language,
'theme' => 'krajee',
'ajax' => [
'url' => \yii\helpers\Url::to(['search-doc']),
'dataType' => 'json',
'data' => new JsExpression('function (params) { return {q:params.term}; }'),
],
'errorLoading' => new JsExpression("function () { return '".Yii::t('app', 'Waiting for data...')."'; }"),
'escapeMarkup' => new JsExpression("function (markup) { return markup; }"),
'templateResult' => new JsExpression("function (bibliography) { return bibliography.title; }"),
'templateSelection' => new JsExpression("function (bibliography) { return bibliography.title; }"),
],
]) ?>
--------控制器------------
public function actionSearchDoc($q = null)
{
Yii::$app->response->format = \yii\web\Response::FORMAT_JSON;
$out = ['id' => '', 'title' => '', 'author' => ''];
if ($q) {
$query = new yii\db\Query;
$query->select('id, title, author')
->from('bibliography')
->where(['like', 'title', $q])
->orWhere(['like', 'author', $q])
->limit(50);
$command = $query->createCommand();
$data = $command->queryAll();
$out = array_values($data);
}
return \yii\helpers\ArrayHelper::map($out, 'id', 'title', 'author');
}
根据 Kartik 的 Select2 docs,当 optgroups 存在时,ArrayHelper::map 是可行的方法,但我无法解决这个问题,因为结果下拉列表总是空的。这是来自 ArrayHelper::map:
的示例 JSON 字符串{"results":{"Author1":{"4":"DocumentFoo1","121":"DocumentFoo2","219":"DocumentFoo3","197":"DocumentFoo4","198":"DocumentFoo5","2":"DocumentFoo6","273":"DocumentFoo7"},"Author2":{"68":"DocumentThee1"}}}
有什么想法吗?
这是我自己想出来的。首先,我们必须关心需要的 JSON 字符串以提供基于 AJAX 的 Select2,它必须像这样 (注意特殊关键字 results
、id
、text
和 children
要求基于 AJAX 的 Select2 构建 optgroups):
Array
(
[results] => Array
(
[0] => Array
(
[text] => "author1"
[children] => Array
(
[0] => Array
(
[id] => "id1"
[text] => "title1"
)
[1] => Array
(
[id] => "id2"
[text] => "title2"
)
)
)
[1] => Array
(
[text] => "author2"
[children] => Array
(
[0] => Array
(
[id] => "id3"
[text] => "title3"
)
)
)
)
)
然而,四参数ArrayHelper::map
输出如下:
Array
(
[author1] => Array
(
[id1] => "title1"
[id2] => "title2"
)
[author2] => Array
(
[id3] => "title3"
)
)
所以我们必须重新排列内容并合并那些特殊关键字。因此,正确的控制器操作应该是这样的:
public function actionSearchDoc($q = null)
{
// JSON format result.
Yii::$app->response->format = \yii\web\Response::FORMAT_JSON;
$out['results'] = '';
if ($q) {
$query = Bibliography::find()->select(['id', 'title', 'author'])
->where(['like', 'title', $q])
->orWhere(['like', 'author', $q])
->all();
// Group titles by author.
$authorArray = ArrayHelper::map($query, 'id', 'title', 'author');
// Previous array lacks keywords needed to use optgroups
// in AJAX-based Select2: 'results', 'id', 'text', 'children'.
// Let's insert them.
$results = [];
foreach ($authorArray as $author => $docArray) {
$docs = [];
foreach ($docArray as $id => $title) {
$docs[] = ['id' => $id, 'text' => $title];
}
$results[] = ['text' => $author, 'children' => $docs];
}
$out['results'] = $results;
}
return $out;
}
所以,就是这样。希望对你有帮助。