简体   繁体   English

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

[英]How can I implement a dynamic form in TYPO3?

I have created a extension to manage some courses and now I want to add some dynamic to one of my forms. 我创建了一个扩展程序来管理一些课程,现在我想为其中的一个表单添加一些动态。 This form contains two select fields. 此表单包含两个选择字段。 The first select field specify a course category and the second one a course. 第一个选择字段指定课程类别,第二个选择字段指定课程。 Currently I get always all categories and all courses no matter which category is selected. 目前,无论选择哪个类别,我总是得到所有类别和所有课程。

Now I would like that a user can only select a course which belongs to a selected category, but I don't know how I can implement this. 现在,我希望用户只能选择属于所选类别的课程,但是我不知道该如何实现。

I have tried to use a typeNum and some ajax, but I don't know how I can change the form model with the ajax call and without a page reload. 我尝试使用typeNum和一些Ajax,但是我不知道如何通过ajax调用和不重新加载页面的方式来更改表单模型。

My template for this form looks like the following: 我用于此表单的模板如下所示:

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

As you can see it is a simple form with two select fields, a submit button and a hidden field which stores the page id. 如您所见,它是一个简单的表单,具有两个选择字段,一个提交按钮和一个存储页面ID的隐藏字段。 I don't want to submit the form when the category is changed so I think there is no way to implement this dynamic without ajax. 我不希望在更改类别时提交表单,因此我认为没有ajax就无法实现此动态。

For this reason I have implemented the following typenum: 因此,我实现了以下typenum:

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
}

After that I have added some javascript (jQuery) to execute a controller action via ajax when the select field is changed: 之后,当选择字段更改时,我添加了一些JavaScript(jQuery)通过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);
            }
        });
    });
});

Simple action: 简单的动作:

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

If I change the select field I get the message "ajax call fired". 如果更改选择字段,则会收到消息“已触发ajax呼叫”。 So my controller action will be executed and I might implement some "get courses by requested category id" logic and so on now, but how can I update the form from above which will be rendered by my sidebarAction with the ajax call and without a page reload? 因此,将执行我的控制器操作,并且现在可以实现一些“通过请求的类别ID获取课程”逻辑,依此类推,但是如何从上方更新表单,该表单将由我的sidebarAction使用ajax调用呈现而没有页面重新加载?

Ok, I found a way to get it work. 好的,我找到了一种使它工作的方法。

At first I changed the ontent type of my typeNum from above to json, because I want to work with json. 最初,我将typeNum的ontent类型从上面更改为json,因为我想使用json。

additionalHeaders = Content-type: application/json

Then I changed my ajax call: 然后我更改了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();
    });

});

And my controller action for this ajax request looks as follows: 我对这个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);

}

Your feedback is welcome :). 欢迎您提供反馈意见:)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM