I'm currently developing a grails 1.3.7 application, which will be used for organizing lectures, seminars and university related stuff. In this context, tutors should be able to assign topics the students previously selected. For that purpose, I use a simple table 'matrix' with students on the right and the available topics as table headers. Now the tutors want me to implement, that the table rows are draggable. I achieved this with a jQuery plugin, and it all works fine, but I must also save the new order of the rows somewhere, so I decided to save it as an ArrayList in a domain class. I implemented a simple logic to wipe the list and rebuild it everytime the tutor saves the topic assignments.
The code for those steps:
Domain Class
class Seminar extends AbstractLecture {
...
ArrayList<Integer> studentOrder = new ArrayList<Integer>()
...
gsp: The hiddenField holds the serialized representation of the new row order, set by a javascript function (works fine).
<g:form action="saveDistribution">
<g:hiddenField name="order" id="order" value=""/>
...
Controller
The plugin serializtion function returns a string I'm breaking down here, this is also no problem and the ids are correctly contained in the list after this block.
def saveDistribution = {
....
if (!params.order.toString().equals("")) {
seminar.studentOrder.clear() //seminar is the domain object
def temp = params.order.toString().replace('[','').replace(']','').replace("table-1=", "").replaceFirst('&', '')
def split = temp.split("&")
for (id in split) {
seminar.studentOrder.push(Integer.parseInt(id)) //Works fine
}
}
//If I check seminar.studentOrder here, the parsed values are present
//Now I redirect to another function (forward would also work, doesn't matter here)
redirect(action: "distributeTopics", id: params.id)
But now the big problem: When I check seminar.studentOrder right after the redirect, the list is completly empty... and I really, really don't know why. I driving me nearly insane for the last hours :( I tried everything I could even imagine to solve this problem, but nothing is willing to work. Now I'm urged to think that I'm missing a big point somewhere.
I appreciate everything you can contribute to solve this problem. If you need more code, or even the complete code for this context, I will provide it.
Many thanks in advance, Dominic
UPDATE (Complete code added for both controller functions):
Here is the code from distributeTopics:
The TopicTableDataWrapper Class is a simple Java class to gather necessary data so that I have an easier time in the gsp.
As you can see, I'm simply pulling the student objects from the database with the supplied IDs from the ArrayList studentOrder, but since the list is always empty and save doesn't work either... well, I'm stuck here.
def distributeTopics = {
def seminar = Seminar.findById(params.id)
if (!seminar) {
flash.message = "Error: Seminar not found. (Database error?)"
redirect(controller: "lecture", action: "list")
}
/*
* Gather all students and build an ArrayList<TopicTableDataWrapper>, which will be passed to the gsp.
*/
def wrapperList = new ArrayList<TopicTableDataWrapper>()
if (seminar.studentOrder.isEmpty()) {
for (student in seminar.students) {
//Selected topics
def topics = seminar.getPrioritizedTopics(student)
if (topics[0] == null) {
topics = null
}
//Already assigned topic
def assigned = seminar.getAssignedTopic(student)
//Comment
def comment = null
if (seminar.comments.containsKey(student.id.toString())) {
comment = seminar.comments.get(student.id.toString())
}
wrapperList.push(new TopicTableDataWrapper(student, assigned, comment, topics))
}
}
else {
for (studentId in seminar.studentOrder) {
def student = User.findById(studentId)
if (student == null) continue
//Selected topics
def topics = seminar.getPrioritizedTopics(student)
if (topics[0] == null) {
topics = null
}
//Possibly assigned topic
def assigned = seminar.getAssignedTopic(student)
//Comment
def comment = null
if (seminar.comments.containsKey(student.id.toString())) {
comment = seminar.comments.get(student.id.toString())
}
wrapperList.push(new TopicTableDataWrapper(student, assigned, comment, topics))
}
}
/*
* Now we also need a list of all topics.
* It is important that the list is sorted, because we must map the topic titles to the shortcuts in the gsp!
* We do this by building a hashmap which just maps 'T1', 'T2', ... as keys to the topics
*/
def topicList = seminar.topics.sort()
def map = new HashMap<String, Topic>()
def i = 1
for (topic in topicList) {
map.put("T" + i.toString(), topic)
i++
}
[seminar: seminar, wrapperList: wrapperList, topicMap: map, id: seminar.id]
}
def saveDistribution = {
def seminar = Seminar.findById(params.id)
if (!seminar) {
flash.message = "There was a problem while retrieving the seminar (database error?)."
redirect(controller: "lecture", action: "list")
}
/*
* Parse the corresponding radiogroup for every student in the seminar
*/
for (student in seminar.students) {
//Look if a topic has been assigned by checking the params -> "group <student.id>"
if (params.containsKey("group " + student.id)) {
//if that's the case, assign him this topic, but keep his selection for later corrections!
def topic = Topic.findById(Integer.parseInt(params.get("group " + student.id).toString()))
//Remove previously assigned topic for this seminar
def prevTopic = seminar.getAssignedTopic(student)
if (prevTopic != null) {
student.removeFromAssignedTopics(prevTopic)
}
student.addToAssignedTopics(topic)
}
}
if (!params.order.toString().equals("")) {
seminar.studentOrder.clear()
def temp = params.order.toString().replace('[','').replace(']','').replace("table-1=", "").replaceFirst('&', '')
def splitParam = temp.split("&")
for (id in splitParam) {
seminar.studentOrder.push(Integer.parseInt(id))
}
}
flash.message = "Distribution saved."
seminar.save(failOnError: true) //Still empty list after redirect
redirect(action: "distributeTopics", id: params.id)
}
.save()before redirect? (it's not exist in this example). What if call it as.save(failOnError: true)? - Igor Artamonov.save()method used? - Igor ArtamonovList studentOrder = []instead? - Igor Artamonov