1

I have some working JS code which I put on the sections of my create and edit views, and it's working fine.

However, when I attempted to move the code to a separate JS file, the code would no longer call the controller action.

Here the JS code:

<g:javascript>
    $(document).ready(function(){
        <g:remoteFunction controller="project" action="ajaxGetClient" onSuccess="updateClient(data)"/>
    });
    function updateClient(data){
        var element = $("#project\\.client");
        element.empty();
        element.val(data.name);
    }
</g:javascript>

Here's the controller action:

def ajaxGetClient = {
    if(!params.id){
        params.id = Project.find("FROM Project ORDER BY id").id
    }
    def projectInstance = Project.get(params.id)
    render projectInstance?.client as JSON
}

And here's the GSP code:

<g:textField name="project.client" id="project.client" maxlength="9" required="" disabled=""/>

<g:select id="project" name="project.id" from="${myPackage.Project.list()}" optionKey="id" required="" value="${productInstance?.project?.id}" class="many-to-one"
                    onchange="${
                        remoteFunction(
                            controller: 'project',
                            action: 'ajaxGetClient',
                            onSuccess: 'updateClient(data)',
                            params: '\'id=\' + this.value'
                    )}"
/>

I added a resource to ApplicationResources.groovy and changed the above JS code to this:

<g:javascript library="updateclient"/>

I simply copy/pasted the code into a JS file and then got a message:

Uncaught SyntaxError: Unexpected token <

which I understood came from it not recognizing the GSP syntax, so I tried some AJAX, which I'm pretty unexperienced at:

$(document).ready(function(){
    $.ajax({
        type: 'POST',
        url: "${remoteFunction(controller:'project', action:'ajaxGetClient', onSuccess:'updateClient(data)')}"
    });
});

Here's what I'm getting from the browser console:

http://localhost:8080/MyApp/product/$%7BremoteFunction(controller:'project',%20action:'ajaxGetClient',%20onSuccess:'updateClient(data)')%7D 404 (Not Found)

Quite frankly, I'm at a loss right now. Any help would be appreciated.

victorantunes
  • 1,141
  • 9
  • 20

2 Answers2

4

The reason for this is that Javascript (.js) and other non GSP (.gsp) files aren't parsed through the Groovy server pages engine. Thus, tag libraries such as the or ${g.remoteFunction} aren't parsed.

There are several ways to accomplish this however.

One is to keep the code in your GSP and not externalize it into javascript files.

Second is to move your code into javascript files but have configuration values in your GSP file. Here is a very simple example of using the message taglib:

// inside the .js file
function myFunction() {
  console.log("I would use this value: "+_VALUE_FROM_GSP);
}

<script type="text/javascript">
// inside the .gsp file
var _VALUE_FROM_GSP = "${message(code: 'just.an.example')";
</script>

Finally, there plugins (listed below) that allows you specify some resources (javascript files in your case) to be parsed through the Groovy Server Pages engine.

GSP-arse plugin and GSP Resources

Joshua Moore
  • 24,706
  • 6
  • 50
  • 73
1

I'll be answering my own question here, since the bulk of it came from valuable advice from a friend of mine, but Joshua's answer was also very important, so I ended up combining both of them.

This is how I solved it:

On the GSP:

<script type="text/javascript">
    var _URL = '${resource(dir: "")}/project/ajaxGetClient';
</script>
<g:javascript library="updateclient"/>

The reason I'm using the <script> tag is because in order for the _URL variable to become usable across different files, it had to be declared before the file using it. At least that's what this other SO answer said:

Global variables in Javascript across multiple files

Separate JS file:

$(document).ready(function(){
    getClientAjax(null);
});
function getClientAjax(id) {
    $.ajax({
        url: _URL,
        type: "POST",
        data: { id: id },
        success: function(data) {
            updateClient(data);
        }
    });
}
function updateClient(data){
    var element = $("#project\\.client");
    element.empty();
    element.val(data.name);
}

And the controller action remained the same.

At the end, there had to be created another JS function, but I gotta say I'm happy with the result.

Thanks for all the help.

Community
  • 1
  • 1
victorantunes
  • 1,141
  • 9
  • 20