使用 Ajax + RenderPartial/Ajax 动态更新 ActiveForm 值时出现问题

Problem updating dynamically ActiveForm values with Ajax + RenderPartial/Ajax

解决方案

由于 php 不会被重新执行,有人告诉我使用来自控制器的 return 值作为 "success" 函数的参数进入 ajax 的请求.
**控制器**
if(Yii::$app->request->isAjax){
        $query = new \yii\db\Query();
        $rows = $query->select([])
            ->from('task')
            ->where('date(start) <= date(\'' . $this->request->getBodyParam('start_date') . '\')')
            ->all();
        $items = "";

        foreach (ArrayHelper::map($rows,'id','name') as $key => $value)
            $items .= '<option value="'. $key .'">'. $value .'</option>\n';
        //<option value="16">test</option> example output
        echo $items;
    }

VIEW

$this->registerJs("$('#task-start').on('change',function(){
            $(\".btn, .btn-success\").prop(\"disabled\",true);
            var date = $(this).val();
            $.ajax({
                url: \"".Yii::$app->request->baseUrl."/task/create\",
                data: {start_date: date},
                type: \"post\",
                success: function(dependency_options){ 
                //dependency_options contains what's returned with 'echo' from the controller  
                $('#task-dependencies').find('option:not(:first)').remove();
                    $('#task-dependencies').append(dependency_options);
                    $(\".btn, .btn-success\").prop(\"disabled\",false);
                },
                error: function () {
                console.log('ERROR')
                $(\".btn, .btn-success\").prop(\"disabled\",false);
                }
            });
    });",View::POS_READY);

希望这可能对某人有所帮助。

我的问题

我有一个没有元素的 DropDownList,每当用户更改日期选择器而不刷新页面时,我想用来自查询的元素更新列表。

与此类似的示例是您在其中键入您所在地区的那些表单,它会根据您之前在字段中选择的内容更改下拉列表。

也许我使用了错误的方法来解决这个问题,因为我对 MVC 模型和 Yii2 框架还是陌生的,所以任何关于如何改变它的想法都非常感谢。

我试过的

使用下面的代码我遇到了问题,因为在第一次创建表单后我以后无法更改它,我尝试更改 html,正如您从成功的脚本中看到的那样 ajax 视图的函数,但脚本仅在第一次加载视图时执行。

调用渲染器的控制器

public function actionCreate()
    {
        $model = new Task();
        if(Yii::$app->request->isAjax){
            $query = new \yii\db\Query();
            $rows = $query->select([])
                ->from('task')
                ->where('date(start) <= date(\'' . $this->request->getBodyParam('start_date') . '\')')
                ->all();
            $items = ArrayHelper::map($rows,'id','name');
            $model->setItems($items);

            return $this->renderPartial('_form',[
                'partial' => true,
                'model' => $model
            ]);
        }
        else if ($this->request->isPost) {
            ..unnecessary code..
        return $this->render('create', [
            'model' => $model,
        ]);
    }

视图“创建”基本上呈现视图 _form(由 Gii 自动生成)

查看_表格

<?php
//Here it takes the items in the model
//(which will contain the new items to append after ajax call)
$objects = json_encode($model->getItems() ?? []); 
var_dump($model->getItems() ?? []);

//Here whenever the datepicker is change will fire ajax request
$this->registerJs("$('#task-start').on('change',function(){
        var date = $(this).val();
        var items = ". json_encode($model->getItems() ?? []) .";
        alert(items);
        $.ajax({
            url: \"".Yii::$app->request->baseUrl."/task/create\",
            data: {start_date: date},
            type: \"post\",
            success: function(){
                //$('#task-dependencies').find('option:not(:first)').remove();
                $.each(items, function(key, value) {
                    $('#task-dependencies')
                      .append($('<option>', { value : key })
                      .text(value));
                });
            },
            error: function () {
            console.log('ERROR')
            }
        });
});",View::POS_READY);
?>

<?php $form = ActiveForm::begin(); ?>

    <?= $form->field($model, 'start')->widget(\kartik\date\DatePicker::className(), [
        ...datepicker that triggers onChange...
    ]) ?>

    //The dropdownlist that should dynamically change
    <?= $form->field($model, 'dependencies')->dropDownList(
            $model->getItems(),
            ['prompt' => 'Seleziona una o più dipendenze', 'multiple' => true, 'selected' => 'selected']    // options
        );
    ?>

    <?php ActiveForm::end(); ?>

</div>

<script src="https://cdn.jsdelivr.net/npm/jquery@3.6.0/dist/jquery.min.js" integrity="sha256-/xUj+3OJU5yExlq6GSYGSHk7tPXikynS7ogEvDej/m4=" crossorigin="anonymous"></script>
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.3.1/css/all.css">

你可以在yii2中使用Pjax:
控制器:

public function actionCreate() {
        $model = new Task();
        if( Yii::$app->request->post()  && Yii::$app->request->isPjax ) {
            $query = new \yii\db\Query();
            $rows = $query->select([])
                ->from('task')
                ->where('date(start) <= date(\'' . $this->request->getBodyParam('start_date') . '\')')
                ->all();
            $items = ArrayHelper::map($rows,'id','name');
            $model->setItems($items);

            // Alert widget renders a message from session flash.
            // Yii::$app->session->setFlash('info', "Ok....");

            return $this->renderAjax('_form',[ // Or renderPartial
                'partial' => true,
                'model' => $model
            ]);
        }
        // else if ($this->request->isPost) {
            // ..unnecessary code..
        return $this->render('create', [
            'model' => $model,
        ]);
    }
}

查看

 // submitEvent: The jQuery event that will trigger form handler. Defaults to "submit".
<?php Pjax::begin(['submitEvent' => 'change']); ?>

     <?php $form = ActiveForm::begin([
       'options' => ['data-pjax' => ''],
     ]);
            
            // if(hasFlash ....){ // If used ...
            // Yii::$app->session->getFlash('info')
            // }
     ?>
            <?= $form->field($model, 'start')->widget......
            <?= $form->field($model, 'dependencies')->dropDownList(
            $model->getItems(),
            // ......

    <?php ActiveForm::end(); ?>

<?php Pjax::end(); ?>

提示:以上代码将满足您的目标。但是你可以使用下面的代码来改变更多并响应Pjax事件。
jQuery 或 JavaScript...

$(document).on('pjax:send', function() {  
  // code ... Example: $('#loading').css({"visibility":"visible"}); //show()
});
$(document).on('pjax:complete', function() {
  // code ... // hide()
});

// Or use if Pjax::$submitEvent = 'submit'
// $(document).on('change', '#id', function(event) { $(this).submit(); });

如果还有问题,请检查SQL和....
中的日期格式方法 祝你好运。