对控制器的异步调用 - 用于州和县

时间:2014-12-31 15:35:07

标签: grails asynchronous controller

在Grails中 - 我需要创建一个控制器方法来填充State和County下拉表单字段,这样当选择State时,它只会将该州的县填入County下拉列表。

一位同事告诉我这是Grails的异步调用,但我是Grails的新手,我真的不知道那是什么或如何开始。任何帮助将不胜感激。

这是我的代码片段:

目前使用Grails 2.43。我有两个域类(州和县),以及州和县的两个选择下拉列表。

表单元素:

<g:select name="locationState" class="form-control" from="${....State.list().sort{it.orderNumber}}">

<g:select name="locationCounty" class="form-control" from="${...State.FindByName(it.orderNumber).counties}">

以下是示例类:

 class State {

        static hasMany = [county:County]

        String name
        String value
        int orderNumber = 0

        static constraints = {
            name nullable:false, maxSize:50, blank:false
            value nullable:false, maxSize:100, blank:false
        }

        String toString(){
            "$value"
        }

        static mapping = {
            table 'state'
            cache: 'read-write'
            columns{
                id column:'id'
                name column:'name'
                value column:'value'
                orderNumber column:'order_number'
            }
            id generator: 'assigned'
        }
    }


    class County {

        State state
        String county

        static constraints = {
            state nullable:false
            county nullable:false, maxSize:100, blank:false
        }

        String toString(){
            "${state.name} - $county"
        }

        static mapping = {
            table 'county'
            cache: 'read-write'
            columns{
                id column:'id'
                county column:'county'
                state column:'state_id'
            }
            id generator: 'assigned'
        }
    }

1 个答案:

答案 0 :(得分:1)

注释中链接的异步指南用于编写异步调用。例如,如果您有两个计算成本高的方法调用(或需要网络I / O的方法),您可以使用线程(大致)并行运行它们。 Grails提供了许多不同的帮助程序,使这种异步编程非常容易。

但是,这不太可能是您的GORM查询所需要的。您想要填充第二个选择框。您可以通过在选择状态后重新加载页面或使用JavaScript填充框来完成这两种方式。我假设你想做后者。 Grails 提供工具(例如<g:remoteFunction />标签)来处理这个问题,而无需编写自己的JavaScript,但Grails AJAX库已被弃用并且其用途是不推荐。

相反,您应该编写自己的JavaScript。我将向您展示一种使用jQuery的技术:

在您的视图中,初始化两个选择,但第二个应初始化为空。我们还将为他们提供ID,以便更容易从jQuery中选择:

<g:select name="locationState"
    class="form-control"
    from="${....State.list().sort{it.orderNumber}}"
    id="location-state" />
<g:select name="locationCounty"
    class="form-control"
    from="${[]}"
    id="location-county" />

然后,当用户选择状态时,我们需要在控制器上公开一个动作来加载县:

def loadCountiesByState() {
    def state = params.state
    def counties = State.findByValue(state).counties
    render g.select(name: 'locationCounty', class: 'form-control',
            from: counties, id: 'location-county')
}

您应该只需将浏览器指向/app-name/controller-name/loadCountiesByState?state=CA即可测试此部分。我并不确切知道您的数据是如何建模的,因此您可能需要更改State.findByValue(state)部分以满足您的需求。

现在我们只需要用一些JavaScript连接控件。确保包含jQuery。

<script type="text/javascript">
    $(function() {
        $('#location-sate').change(function() {
            var state = $(this).val();
            $.ajax({
                url: '/app-name/controller-name/loadCountiesByState',
                date: { state: state },
                success: function(data) {
                    $('#location-county').replaceWith(data);
                }
            });
        });
    });
</script>

这将使用一个应该完全填充县的新选择替换下拉列表。