如何将模型数据加载到在 Yii 中使用 Ajax 过滤的 Select2 下拉列表
我在视图中使用以下 select2 Yii 小部件来填充下拉列表.由于准备选择列表所需的数据包含超过 2K 条记录,我使用带有 minimumInputLength 参数的 select2 和一个 ajax 查询来根据用户输入生成列表的部分结果.如果我创建一个新记录,我完全没有问题.它填充一切正常,我可以将数据保存到我的数据库中.但是,我不知道如何在更新操作期间将保存的数据加载回此下拉列表.我在某处读到了用于此目的的 initselection,但我不知道如何使用它.
I use the following select2 Yii widget in my view to populate a drop-down list. Since the data necessary for the preparation of the select list consists of more than 2K records I use select2 with minimumInputLength parameter and an ajax query to generate partial result of the list based on user input. If I create a new record I have no problem at all. It populates everything fine and I can save data to my database. However I don't know how to load saved data back to this drop-down during my update action. I read somewhere that initselection intended for this purpose but I couldn't figure out how to use it.
有人可以帮我解决这个问题吗?
Can someone help me out on this?
我的观点:
$this->widget('ext.select2.ESelect2', array(
'selector' => '#EtelOsszerendeles_osszetevo_id',
'options' => array(
'allowClear'=>true,
'placeholder'=>'Kérem válasszon összetevőt!',
'minimumInputLength' => 3,
'ajax' => array(
'url' => Yii::app()->createUrl('etelOsszerendeles/filterOsszetevo'),
'dataType' => 'json',
'quietMillis'=> 100,
'data' => 'js: function(text,page) {
return {
q: text,
page_limit: 10,
page: page,
};
}',
'results'=>'js:function(data,page) { var more = (page * 10) < data.total; return {results: data, more:more }; }',
),
),
));?>
我的控制器的动作过滤器:
My controller's action filter:
public function actionFilterOsszetevo()
{
$list = EtelOsszetevo::model()->findAll('nev like :osszetevo_neve',array(':osszetevo_neve'=>"%".$_GET['q']."%"));
$result = array();
foreach ($list as $item){
$result[] = array(
'id'=>$item->id,
'text'=>$item->nev,
);
}
echo CJSON::encode($result);
}
推荐答案
我使用 initSelection 以这种方式加载现有记录进行更新(我用 ...
替换了您的一些视图代码以聚焦在主要变化中).用 Yii 1.1.14 测试.本质上,我使用了两个不同的 ajax 调用:
I use initSelection to load existing record for update in this way (I replaced some of your view code with ...
to focus in main changes). Tested with Yii 1.1.14. Essentially, I use two different ajax calls:
查看:
<?php
$this->widget('ext.select2.ESelect2', array(
'selector' => '#EtelOsszerendeles_osszetevo_id',
'options' => array(
...
...
'ajax' => array(
'url' => Yii::app()->createUrl('client/searchByQuery'),
...
...
'data' => 'js: function(text,page) {
return {
q: text,
...
};
}',
...
),
'initSelection'=>'js:function(element,callback) {
var id=$(element).val(); // read #selector value
if ( id !== "" ) {
$.ajax("'.Yii::app()->createUrl('client/searchById').'", {
data: { id: id },
dataType: "json"
}).done(function(data,textStatus, jqXHR) { callback(data[0]); });
}
}',
),
));
?>
现在在您的控制器中,您应该接收用于 ajax 处理的参数:查询 (q),作为字符串,插入时;id (id) 更新时为 int.在 $_GET 中读取时,参数名称必须与 ajax data
参数(在此示例中插入 q
;在更新 id
中)相同.代码未重构/优化:
Now in your controller you should receive parameters for ajax processing: query (q), as string, when inserting; id (id) as int when updating. Parameter names must be same as ajax data
parameters (in this sample insert q
; in update id
) when read in $_GET. Code is not refactored/optimized:
控制器:
public function actionSearchByQuery(){
$data = Client::model()->searchByQuery( (string)$_GET['q'] );
$result = array();
foreach($data as $item):
$result[] = array(
'id' => $item->id,
'text' => $item->name,
);
endforeach;
header('Content-type: application/json');
echo CJSON::encode( $result );
Yii::app()->end();
}
public function actionSearchById(){
$data = Client::model()->findByPk( (int) $_GET['id'] );
$result = array();
foreach($data as $item):
$result[] = array(
'id' => $item->id,
'text' => $item->name,
);
endforeach;
header('Content-type: application/json');
echo CJSON::encode( $result );
Yii::app()->end();
}
模型 - 自定义查询和一点顺序/安全/干净:)
Model - custom query and a little of order / security / clean :)
public function searchByQuery( $query='' ) {
$criteria = new CDbCriteria;
$criteria->select = 'id, ssn, full_name';
$criteria->condition = "ssn LIKE :ssn OR full_name LIKE :full_name";
$criteria->params = array (
':ssn' => '%'. $query .'%',
':full_name' => '%'. $query .'%',
);
$criteria->limit = 10;
return $this->findAll( $criteria );
}
当更新通过传统的 HTTP Post(同步,例如使用 Yii 生成的表单)预加载时,它开箱即用.对于异步/Ajax 更新,例如使用 JQuery:
It works out of box when update is preloaded with traditional HTTP Post (synchronous, for example with Yii generated forms). For async/Ajax updates, for example with JQuery:
事件/触发器:
$('#button').on("click", function(e) {
...
... your update logic, ajax request, read values, etc
...
$('#select2_element').select2('val', id_to_load );
});
这样,initSelection
将再次以异步方式运行,并使用新的 id_to_load
值,通过 id 重新加载记录.
With this, initSelection
will run again in async way with new id_to_load
value, reloading record by id.
根据您的情况和需要,initSelection
可能完全不同,以避免从 db 或 您可以使用formatResult
和formatSelection
自定义函数(在加载远程数据示例源代码中描述).阅读文档,我了解到 initSelection 的回调需要带有 id 和文本元素的 JSON 数据才能正确加载,或者您可以尝试结合这两个概念(此 initSelection 与您的自定义 JS 事件/触发器调用)(未测试):
In your case and for your needs, initSelection
could be complete different to avoid load record from db or you can use formatResult
and formatSelection
custom functions (are described in Load Remote Data sample source code). Reading documentation, I understand that initSelection's callback need JSON data with id and text elements to load properly or you could try to combine both concepts (this initSelection with your custom JS event/trigger call) (not tested):
'initSelection'=>'js:function(element,callback) {
// here your code to load and build your values,
// this is very basic sample
var id='myId';
var text='myValue';
data = {
"id": id,
"text": text
}
callback(data);
}',
或直接触发调用:
$('#button').on("click", function(e) {
...
... ...
$("#select2_element").select2("data", {id: "myId", text: "MyVal"});
});
希望有所帮助.
相关文章