【问题标题】:Grails templatesGrails 模板
【发布时间】:2015-01-26 08:52:05
【问题描述】:

我正在使用 grails 2.4.4。我有三个 gsp 文件。 1._configureMessage(模板) 2._configureProjectId(模板) 3. 索引(视图)

我正在渲染索引中的两个模板。但我收到以下错误。

    Line | Method
->> 1145 | runWorker in java.util.concurrent.ThreadPoolExecutor
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
|    615 | run       in java.util.concurrent.ThreadPoolExecutor$Worker
^    744 | run . . . in java.lang.Thread

Caused by GroovyPagesException: Error processing GroovyPageView: Error executing tag <g:render>: Error executing tag <g:form>: Error evaluating expression [gcmDeviceInstance.projectId] on line [8]: Cannot get property 'projectId' on null object
->>  527 | runWorker in G:\grails workspace\MDM_2.4.4\MDM\grails-app\views\androidGcmSender\gcmIndex.gsp
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 

Caused by GrailsTagException: Error executing tag <g:render>: Error executing tag <g:form>: Error evaluating expression [gcmDeviceInstance.projectId] on line [8]: Cannot get property 'projectId' on null object
->>    8 | doCall    in G:/grails workspace/MDM_2.4.4/MDM/grails-app/views/androidGcmSender/gcmIndex.gsp
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 

Object gcmDeviceInstace 显示为空。我已将 gcmProjectInstance 返回到 index.gsp。我应该再次为模板做吗? 我提供了下面的代码。这是我正在尝试使用的一个 android-gcm 插件,并且是 grails 的新手! :)

AndroidGcmSenderController

package mdm
import java.util.List;
import java.util.Map;

class AndroidGcmSenderController {

    def androidGcmService
    def grailsApplication

    def gcmIndex={
        def gcmDeviceInstance= new GcmDevice()
        gcmDeviceInstance.properties=params
        return[gcmDeviceInstance: gcmDeviceInstance]
    }

//    def configureProjectId={
//        def gcmDeviceInstance= new GcmDevice()
//        gcmDeviceInstance.properties=params
//        gcm
//        return[gcmDeviceInstance: gcmDeviceInstance]
//    }

    def beforeInterceptor = {
        if (params.projectId) {
            params.tokens = (GcmDevice.findAllByProjectId(params.projectId) +
                    GcmDevice.findAllByProjectIdIsNull())*.token
        }
    }

    def configureMessage = {
//        def gcmDeviceInstance= new GcmDevice()
//        gcmDeviceInstance.properties=params
//        return[gcmDeviceInstance: gcmDeviceInstance]

        params.apiKey = grailsApplication.config.android.gcm.api.key ?: ''
        render view:'index', model: params
    }

    def Index = {
        render view:'index', model:params
    }

    def sendMessage = {
        ['deviceToken', 'messageKey', 'messageValue'].each {
            key -> params[key] = [params[key]].flatten().findAll { it }
        }
        def messages = params.messageKey.inject([:]) {
            currentMessages, currentKey ->
            currentMessages << [ (currentKey) : params.messageValue[currentMessages.size()]]
        }
        flash.message = 'received.message.response'
        flash.args = [androidGcmService.sendMessage(messages, params.deviceToken,
                params.collapseKey, params.apiKey).toString()]
        redirect(action:'index', params: params)
    }
}

GcmDevice 域

package mdm

class GcmDevice {

    String token
    String projectId


    static constraints = {
        token(nullable:false, blank:false, unique:true)
        projectId(nullable:true)
    }

}

gcmIndex.gsp

<html>
<head>
    <meta name="layout" content="main" />
    <title><g:message code="sender.title" /></title>
</head>
<body>
<div id="projectIdConfiguration">
    <g:render template="androidGcmSender/configureProjectId" />
</div>
<div id="messageConfiguration">
    <g:if test="${gcmDeviceInstance.projectId}">
        <g:render template="androidGcmSender/configureMessage" />
    </g:if>
</div>
<script type="text/javascript">
    ajaxifyLink("form[name='projectId']", "#content", "action", "submit", "POST");
    jQuery("input[name='projectId']").change(function(e) {
        jQuery(form[name='projectId']).submit();
    });
</script>
<g:if test="${request.xhr && gcmDeviceInstance.projectId && !flash.message}">
    <script type="text/javascript">
        jQuery("div#messageConfiguration").show("slide", { direction: "up" }, 300);
        jQuery("div#messageConfiguration").effect("bounce", { times: 3, distance: 10 }, 200);
    </script>
</g:if>
</body>
</html>

_configureMessage.gsp

<p class="usage"><g:message code="sender.usage.message" /></p>
<g:form name="message" action="sendMessage" controller="AndroidGcmSender">
    <g:hiddenField name="projectId" value="${gcmDeviceInstance.projectId}" />
    <div class="formEntryContainer">
        <div class="labelContainer">
            <label for="deviceToken"><g:message code="sender.form.deviceToken"/></label>
        </div>
        <div class="inputContainer">
            <g:each var="token" in="${[deviceToken].flatten()}">
                <div class="toDupe">
                <g:select name="deviceToken" from="${tokens}" value="${token}" noSelection="['':'-']"/>
                </div>
            </g:each>
        </div>
        <div class="actionsContainer">
            <button type="button" class="add dupeParam deviceToken">
                <img src="${resource(dir: 'images/skin',file:'add.png')}" alt="${message(code:'add')}" border="0" />
            </button>
        </div>
    </div>

    <div class="formEntryContainer">
        <div class="labelContainer">
            <label for="apiKey"><g:message code="sender.form.apiKey"/></label>
        </div>
        <div class="inputContainer">
            <g:textField name="apiKey" value="${apiKey}" />
        </div>
        <div class="actionsContainer">
        </div>
    </div>

    <div class="formEntryContainer">
        <div class="labelContainer">
            <label for="collapseKey"><g:message code="sender.form.collapseKey"/></label>
        </div>
        <div class="inputContainer">
            <g:textField name="collapseKey" value="${collapseKey}" />
        </div>
        <div class="actionsContainer">
        </div>
    </div>

    <div class="formEntryContainer">
        <div class="labelContainer">
            <g:message code="sender.form.message"/>
        </div>
        <div class="inputContainer">
            <g:each var="key" in="${[messageKey].flatten()}" status="index">
                <div class="toDupe">
                    <div style="display:table"><div style="display:table-row">
                        <div style="display:table-cell">
                            <label for="messageKey"><g:message code="sender.form.messageKey" /></label>:
                        </div>
                        <div style="display:table-cell">
                            <g:textField name="messageKey" value="${key}" />
                        </div>
                    </div>
                        <div style="display:table-row">
                            <div style="display:table-cell">
                                <label for="messageKey"><g:message code="sender.form.messageValue" /></label>:
                            </div>
                            <div style="display:table-cell">
                                <g:textField name="messageValue" value="${[messageValue].flatten()[index]}" /><br/>
                            </div>
                        </div></div>
                </div>
            </g:each>
        </div>
        <div class="actionsContainer">
            <button type="button" class="add dupeParam">
                <img src="${resource(dir: 'images/skin',file:'add.png')}"
                     alt="${message(code:'add')}" border="0" />
            </button>
        </div>
    </div>

    <div class="formEntryContainer">
        <div class="submitContainer">
            <g:submitButton name="send" value="${message(code:'send')}" />
        </div>
    </div>
</g:form>

<script type="text/javascript">
    jQuery("input[name='multicast']").attr("disabled", "disabled");
    jQuery(".actionsContainer button.dupeParam").click(function(e) {
        var prev = jQuery(this).parent().prev('.inputContainer');
        var toClone = prev.children('.toDupe :first');
        toClone.clone().appendTo(prev);
    });
    ajaxifyLink("form[name='message']", "#content", "action", "submit", "POST");
</script>

_configureProjectID.gsp

<p class="usage"><g:message code="sender.usage.projectId" /></p>
<g:form name="projectId" action="configureMessage" controller="AndroidGcmSender">
    <div class="formEntryContainer">
        <div class="labelContainer">
            <label for="projectId"><g:message code="sender.form.projectId"/></label>
        </div>
        <div class="inputContainer">
            <g:textField name="projectId" value="${gcmDeviceInstance.projectId}" />
        </div>
        <div class="actionsContainer">
            <g:submitButton name="refresh" value="${message(code:'refresh')}" />
        </div>
    </div>
</g:form>

【问题讨论】:

    标签: android grails groovy google-cloud-messaging


    【解决方案1】:

    是的,您必须使用g:rendermodel 属性将数据传递给模板。

    例如,将gcmIndex.gsp 的第 8 行更改为:

    <g:render template="androidGcmSender/configureProjectId" model="['gcmDeviceInstance':gcmDeviceInstance]"/>
    

    【讨论】:

      【解决方案2】:

      你用过的地方

      ${gcmDeviceInstance.projectId}
      

      你可以使用 null 安全属性

      ${gcmDeviceInstance?.projectId}    // notice the question mark after the domain instance
      

      【讨论】:

        猜你喜欢
        • 2013-11-04
        • 1970-01-01
        • 1970-01-01
        • 2010-12-17
        • 2011-03-14
        • 2010-11-30
        • 1970-01-01
        • 1970-01-01
        • 2011-02-13
        相关资源
        最近更新 更多