如何在 TYPO3 中实现动态表单?

How can I implement a dynamic form in TYPO3?

我已经创建了一个扩展来管理一些课程,现在我想在我的一个表单中添加一些动态。此表单包含两个 select 字段。第一个 select 字段指定课程类别,第二个字段指定课程。目前我总是得到所有类别和所有课程,无论哪个类别是 selected.

现在我希望用户只能 select 属于 selected 类别的课程,但我不知道如何实现。

我尝试使用 typeNum 和一些 ajax,但我不知道如何通过 ajax 调用更改表单模型而不重新加载页面。

此表单的模板如下所示:

<f:layout name="Default" />
<f:section name="main">
    <div class="sidebar-view">
        <a id="form"></a>
        <f:form action="list" name="form" object="{form}" section="form">
            <fieldset>
                <f:render partial="FormErrors" arguments="{field: 'form.category'}" />
                <f:form.select class="category" property="category" options="{categoryOptions}" optionValueField="key" optionLabelField="value" prependOptionLabel="{f:translate(key: 'LLL:EXT:courses/Resources/Private/Language/locallang_db.xlf:tx_courses_domain_model_form.category')}" />
                <f:render partial="FormErrors" arguments="{field: 'form.course'}" />
                <f:form.select property="course" options="{courseOptions}" optionValueField="key" optionLabelField="value" prependOptionLabel="{f:translate(key: 'LLL:EXT:courses/Resources/Private/Language/locallang_db.xlf:tx_courses_domain_model_form.course')}" />
                <f:form.hidden class="id" property="pageId" />
                <f:form.submit name="send" value="{f:translate(key: 'LLL:EXT:courses/Resources/Private/Language/locallang_db.xlf:tx_courses_domain_model_form.submit')}" />
            </fieldset>
        </f:form>
    </div>
</f:section>

如您所见,它是一个简单的表单,包含两个 select 字段、一个提交按钮和一个存储页面 ID 的隐藏字段。我不想在类别更改时提交表单,所以我认为没有 ajax 就无法实现此动态。

出于这个原因,我实现了以下类型:

obj.ajaxPrototype = PAGE
obj.ajaxPrototype {
    typeNum = 0
    config {
        disableAllHeaderCode = 1
        additionalHeaders = Content-type: text/plain
        xhtml_cleaning = 0
        debug = 0
        no_cache = 1
        admPanel = 0
    }
}

ajaxCall < obj.ajaxPrototype
ajaxCall {
    typeNum = 1001
    10 < tt_content.list.20.courses_p1
}

之后我添加了一些 javascript (jQuery) 以在 select 字段更改时通过 ajax 执行控制器操作:

$(document).ready(function() {
    $('.tx-courses select:first-of-type').on('change', function() {
        $.ajax({
            method: "POST",
            url: "index.php?id=" + $('.id').val(),
            data: "type=1001&tx_courses_p1[action]=check&tx_courses_p1[form][category]="+$('.category').val(),
            success: function(msg) {
                alert(msg);
            }
        });
    });
});

简单操作:

/**
 * check action
 *
 * @return void
 */
public function checkAction() {
    return 'ajax call fired';
}

如果我更改 select 字段,我会收到消息 "ajax call fired"。所以我的控制器动作将被执行,我现在可能会实现一些 "get courses by requested category id" 逻辑等等,但是我如何更新上面的表单,该表单将由我的 sidebarAction 呈现ajax 调用并且没有重新加载页面?

好的,我找到了让它工作的方法。

起初我将我的 typeNum 的内容类型从上面更改为 json,因为我想使用 json。

additionalHeaders = Content-type: application/json

然后我改变了我的 ajax 电话:

$(document).ready(function() {

    var arr;

    var ajaxCall = function() {
    $.ajax({
        method: "POST",
        url: "index.php?id=" + $('.id').val(),
        data: "type=1001&tx_courses_p1[action]=check&tx_courses_p1[form][category]="+$('.category').val(),
        success: function(msg) {
            $('.tx-courses .course option:not(:first-child)').remove();
            arr = $.map(msg, function(el) { return el });
            arr.sort();
            $.each(arr, function(i, val) {
                $('.tx-courses .course').append('<option value="'+val+'">'+val+'</option>');
            });
        }
    });
    };

    // init (if someone submitted the form, but forgot to select a category)
    ajaxCall();

    // someone changed the category
    $('.tx-courses .category').on('change', function() {
        ajaxCall();
    });

});

我对这个 ajax 请求的控制器操作如下所示:

/**
 * check action
 *
 * @return string
 */
public function checkAction() {

    // get arguments
    $args = $this->request->getArguments();

    // create container for courses which are depended on selected category
    $coursesBySelectedCategory = array();

    // check if category was posted and category exists
    if (isset($args['form']['category']) && $this->courseRepository->categoryExists($args['form']['category'])) {

        // get all courses which belongs to this category
        $courses = $this->courseRepository->findByCategoryId($args['form']['category']);

    } else {

        // get all courses
        $courses = $this->courseRepository->findAllNotExpiredCourses();

    }

    // store course names
    foreach($courses as $course) {
        $coursesBySelectedCategory[] = $course->getName();
    }

    // remove double entries
    $coursesBySelectedCategory = array_unique($coursesBySelectedCategory);

    return json_encode($coursesBySelectedCategory);

}

欢迎您提供反馈:)。