ZF2 - 用 Ajax 填充 Select
ZF2 - Populate Select with Ajax
我有我的 ProductsForm.php:
namespace Products\Form;
use Zend\Form\Form;
use Zend\Db\Adapter\AdapterInterface;
use Zend\Db\TableGateway\TableGateway;
use Zend\Db\Sql\Select;
class ProductsForm extends Form {
public function __construct(AdapterInterface $dbAdapter) {
$this->adapter = $dbAdapter;
parent::__construct('products');
$this->add(array(
'name' => 'state',
'type' => 'select',
'attributes' => array(
'class' => 'form-control',
),
'options' => array(
'empty_option' => 'Select...',
'value_options' => $this->getStatesForSelect()
),
));
$this->add(array(
'name' => 'city',
'type' => 'select',
'attributes' => array(
'class' => 'form-control',
),
'options' => array(
'empty_option' => 'Select...',
'value_options' => $this->getCitiesForSelect()
),
));
}
public function getStatesForSelect() {
$dbAdapter = $this->adapter;
$table = new TableGateway('states', $dbAdapter);
$result = $table->select(function (Select $select) {
$select->order('name DESC');
});
foreach ($result as $res) {
$selectData[$res['id']] = $res['name'];
}
return $selectData;
}
public function getCitiesForSelect($state_id) {
??? :(
select from cities where state_id = $state_id ?
}
}
我只想在用户 select "state"... 时执行 getCitiesForSelect(),然后根据 state.id 值[=用数据库中的值填充它13=]
我该怎么做?
首先,不要将方法 getStatesForSelect
和 getCitiesForSelect
放在您的表单中。表单是控制器层的一部分,每个数据库请求都属于模型层:
http://framework.zend.com/manual/current/en/modules/zend.mvc.intro.html
第二:如果你这样做了,你可以创建一个动作,它将 return 一个 json 与请求的状态,并通过 ajax 调用它。要正确加载所有内容并且美观,您还必须对表单进行一些更改:
$this->add(array(
'name' => 'state',
'type' => 'select',
'attributes' => array(
'class' => 'form-control',
'id' => 'select-state',
),
'options' => array(
'class' => 'state-option',
'empty_option' => 'Select...',
),
));
$this->add(array(
'name' => 'city',
'type' => 'select',
'attributes' => array(
'class' => 'form-control',
'id' => 'select-city',
'style' => 'display:none',
),
'options' => array(
'empty_option' => 'Select...',
),
));
我删除了从数据库中获取您的选项的方法,因为如前所述,这应该是您的模型的工作 table。您在控制器中设置这些选项,因为 NandaKumar 已经写过:
$states = $modelTable->getStatesForSelect();
$form->get('state')->setValueOptions($states);
但这只会填满各州,我们还需要一些东西来填满城市!为此,我们将定义一个 ajax 操作来获取这些:
public function stateCitiesAction()
{
if(!empty($_SERVER['HTTP_X_REQUESTED_WITH'])
&& strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest') {
$stateId = $this->params()->fromRoute("id");
// get your cities table
// getCitiesForSelect() needs to return an array!
$cities = $citiesTable->getCitiesForSelect();
return new JsonModel($cities);
} else {
// return a 404 if this action is not called via ajax
$this->getResponse()->setStatusCode(404);
return NULL;
}
}
if 语句是为了确保此操作只能通过 ajax 访问。如果不是,它将 return 一个 404。
我只是假设在这个例子中,模型操作将 return 与表单中的方法相同的数组。尽管您可能会争论哪个级别应该转换数据库结果、模型本身或控制器。但为了让示例简单,我是这样做的。
要正确解析 JsonModel,您需要在 module.config.php 中包含 ViewJsonStrategy。否则你会得到一个错误,因为 Zend 会试图找到一个视图脚本。
'view_manager' => array(
//...
'strategies' => array(
'ViewJsonStrategy',
),
),
此外,我们还需要传递 id。路由参数是执行此操作的最常见方法,我们需要将其包含在我们的路由定义中。此代码不是最终解决方案,仅应向您展示如何在配置中执行此操作:
'poducts' => array(
'type' => 'Segment',
'options' => array(
'route' => '/products/[:controller][/:action][/:id]',
'constraints' => array(
'controller' => '[a-zA-Z][a-zA-Z0-9_-]*',
'action' => '[a-zA-Z][a-zA-Z0-9_-]*',
'id' => '[0-9]*',
),
'defaults' => array(
'__NAMESPACE__' => 'Application\Controller',
'controller' => 'Index',
'action' => 'index',
),
),
),
有关路由的详细信息,请参阅:
http://framework.zend.com/manual/current/en/modules/zend.mvc.routing.html
呼,我们快完成了!唯一剩下的就是填写城市选项的 ajax 调用。我通过 jQuery:
做到了这一点
$(document).ready(function () {
$("#select-state").change(function () {
var stateId = $(this).val();
if(stateId !== "") {
// you might want to change this
var url = "products/index/state-cities/"+stateId;
$.getJSON( url, function( data ) {
var options = "";
$.each(data, function(id, city) {
options += "<option value='" + id + "'>" + city + "</option>";
});
$("#select-city").html(options).fadeIn();
});
}
});
});
不是我不知道你的路由,你可能需要更改 url。
我有我的 ProductsForm.php:
namespace Products\Form; use Zend\Form\Form; use Zend\Db\Adapter\AdapterInterface; use Zend\Db\TableGateway\TableGateway; use Zend\Db\Sql\Select; class ProductsForm extends Form { public function __construct(AdapterInterface $dbAdapter) { $this->adapter = $dbAdapter; parent::__construct('products'); $this->add(array( 'name' => 'state', 'type' => 'select', 'attributes' => array( 'class' => 'form-control', ), 'options' => array( 'empty_option' => 'Select...', 'value_options' => $this->getStatesForSelect() ), )); $this->add(array( 'name' => 'city', 'type' => 'select', 'attributes' => array( 'class' => 'form-control', ), 'options' => array( 'empty_option' => 'Select...', 'value_options' => $this->getCitiesForSelect() ), )); } public function getStatesForSelect() { $dbAdapter = $this->adapter; $table = new TableGateway('states', $dbAdapter); $result = $table->select(function (Select $select) { $select->order('name DESC'); }); foreach ($result as $res) { $selectData[$res['id']] = $res['name']; } return $selectData; } public function getCitiesForSelect($state_id) { ??? :( select from cities where state_id = $state_id ? } }
我只想在用户 select "state"... 时执行 getCitiesForSelect(),然后根据 state.id 值[=用数据库中的值填充它13=]
我该怎么做?
首先,不要将方法 getStatesForSelect
和 getCitiesForSelect
放在您的表单中。表单是控制器层的一部分,每个数据库请求都属于模型层:
http://framework.zend.com/manual/current/en/modules/zend.mvc.intro.html
第二:如果你这样做了,你可以创建一个动作,它将 return 一个 json 与请求的状态,并通过 ajax 调用它。要正确加载所有内容并且美观,您还必须对表单进行一些更改:
$this->add(array(
'name' => 'state',
'type' => 'select',
'attributes' => array(
'class' => 'form-control',
'id' => 'select-state',
),
'options' => array(
'class' => 'state-option',
'empty_option' => 'Select...',
),
));
$this->add(array(
'name' => 'city',
'type' => 'select',
'attributes' => array(
'class' => 'form-control',
'id' => 'select-city',
'style' => 'display:none',
),
'options' => array(
'empty_option' => 'Select...',
),
));
我删除了从数据库中获取您的选项的方法,因为如前所述,这应该是您的模型的工作 table。您在控制器中设置这些选项,因为 NandaKumar 已经写过:
$states = $modelTable->getStatesForSelect();
$form->get('state')->setValueOptions($states);
但这只会填满各州,我们还需要一些东西来填满城市!为此,我们将定义一个 ajax 操作来获取这些:
public function stateCitiesAction()
{
if(!empty($_SERVER['HTTP_X_REQUESTED_WITH'])
&& strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest') {
$stateId = $this->params()->fromRoute("id");
// get your cities table
// getCitiesForSelect() needs to return an array!
$cities = $citiesTable->getCitiesForSelect();
return new JsonModel($cities);
} else {
// return a 404 if this action is not called via ajax
$this->getResponse()->setStatusCode(404);
return NULL;
}
}
if 语句是为了确保此操作只能通过 ajax 访问。如果不是,它将 return 一个 404。
我只是假设在这个例子中,模型操作将 return 与表单中的方法相同的数组。尽管您可能会争论哪个级别应该转换数据库结果、模型本身或控制器。但为了让示例简单,我是这样做的。
要正确解析 JsonModel,您需要在 module.config.php 中包含 ViewJsonStrategy。否则你会得到一个错误,因为 Zend 会试图找到一个视图脚本。
'view_manager' => array(
//...
'strategies' => array(
'ViewJsonStrategy',
),
),
此外,我们还需要传递 id。路由参数是执行此操作的最常见方法,我们需要将其包含在我们的路由定义中。此代码不是最终解决方案,仅应向您展示如何在配置中执行此操作:
'poducts' => array(
'type' => 'Segment',
'options' => array(
'route' => '/products/[:controller][/:action][/:id]',
'constraints' => array(
'controller' => '[a-zA-Z][a-zA-Z0-9_-]*',
'action' => '[a-zA-Z][a-zA-Z0-9_-]*',
'id' => '[0-9]*',
),
'defaults' => array(
'__NAMESPACE__' => 'Application\Controller',
'controller' => 'Index',
'action' => 'index',
),
),
),
有关路由的详细信息,请参阅: http://framework.zend.com/manual/current/en/modules/zend.mvc.routing.html
呼,我们快完成了!唯一剩下的就是填写城市选项的 ajax 调用。我通过 jQuery:
做到了这一点$(document).ready(function () {
$("#select-state").change(function () {
var stateId = $(this).val();
if(stateId !== "") {
// you might want to change this
var url = "products/index/state-cities/"+stateId;
$.getJSON( url, function( data ) {
var options = "";
$.each(data, function(id, city) {
options += "<option value='" + id + "'>" + city + "</option>";
});
$("#select-city").html(options).fadeIn();
});
}
});
});
不是我不知道你的路由,你可能需要更改 url。