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=]

我该怎么做?

首先,不要将方法 getStatesForSelectgetCitiesForSelect 放在您的表单中。表单是控制器层的一部分,每个数据库请求都属于模型层: 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。