Vegaaaa Vegaaaa - 6 months ago 40
AngularJS Question

Grails 3 and angular - How to pass input parameters to backend controller

I am sorry for this question in advance, but I don't know what to do anymore. I have recently started with AngularJS and Grails 3 and I am somewhat confused of the dataflow in the whole. I am looking for an explicit explanation for this since days but I didn't come up with any good sources fitting to my problem.

We have some data models, name them Foo, which have a relation to other objects, name them Bar:

class Foo implements Serializable{
Date dateCreated
Date lastUpdated

String name
Bar bar
C c
...
}


and

class Bar implements Serializable {

String name
String usid

C c
D d
E e
}


Now I want to have one input dialogue in which I can fill in the needed data for Object Foo to save cascading all objects with one http request in the database.

My problem now is that since I am new to angularJS I don't know how to create the relational objects and use them in the data object Foo. I am having the information needed to build object Bar in my JSON but I can't access it in the backend since the save method in the backend is invoked with the Datatype Foo and thus Bar is null in Foo.

Until now I have a frontend controller for Foo and after a request Foo.controller injects an Foo.service with action: 'save' such that in the backend a method save is somehow invoked.

Here are the important code parts:

Frontend controller:

function FooCreateController(fooService, $routeParams, $location) {
var vm = this;
vm.save = function (foo) {
fooService.save({action: 'save'}, foo, function (res) {
if (res.id) {
$location.path("/foo/" + res.id);
}
else {
alert("Unknown error occurred");
}
})
}
}


fooDataFactoryService:

angular
.module("fooPackage.foo")
.factory("fooDataFactoryService", fooDataFactoryService);

function fooDataFactoryService(DomainServiceFactory) {
return DomainServiceFactory('/foo/:action/:fooId', {fooId: '@id', action: '@action'},
{"show" : {method: "GET"}},
{"save" : {method: "POST"}},
{"delete" : {method: "DELETE"}},
{"update" : {method: "PUT"}}
);
}


Groovy backend controller:

def save(Foo foo) {
if (foo == null) {
transactionStatus.setRollbackOnly()
render status: NOT_FOUND
return
}

if (foo.hasErrors()) {
transactionStatus.setRollbackOnly()
respond foo.errors, view:'create'
return
}

foo.save flush:true

respond foo, [status: CREATED, view:"show"]
}


How can I achieve this? I don't want to invoke the backend save method with the data type Foo but with my input params from the request. Or is there any better approach for this?

I do not understand enough of Angular yet but this is very important to be finished this weekend and I definitly need any kind of help. :-(

Big thanks in advance!

Answer

I forgot to edit my answer after finally figuring out the solution for this.

The reason for my confusion was the missing knowledge I had about how grails works. My background is NodeJS in greater terms and some Java experience as well. I was just used to use an request Object encapsulating the request params of a POST request in its body.

In NodeJS I recieve the request params via a parameter in the function call ( function(req, res, next), req encapsulating the http data ).

The problem in grails was, that this data was already accessible even though it has never been defined anywhere in my backend controller: The request and the params objects!

http://docs.grails.org/3.1.1/ref/Controllers/params.html

I just needed to add the following code in my backend controller:

params.putAll(request.JSON as Map)

and delete the input parameter of my save method, which lead to:

def save() {
   params.putAll(request.JSON as Map)

   log.println(params)
}

The magic which happens in grails can be very confusing when having another background especially if you don't have the time to get used to it via some tutorials.

Cheers,

Vegaaaa