Save multiple selected dropdown values into a single column in Grails - grails

How to save multiple selected dropdown values into a single column in Grails?
Input will look like
<g:select name="item1Price" from="${1..10}"/>
<g:select name="item2Price" from="${1..10}"/>
<g:select name="item3Price" from="${1..10}"/>
And Output Should be stored in one field
ItemPrice: 2,8,6

Your question is a bit vague, so hopefully a somewhat vague answer will be helpful too!
If you have a domain object Foo:
class Foo {
String itemPrice
}
Then in your controller action, you can just do something like:
def save() {
Foo f = new Foo()
f.itemPrice = [params.item1Price, params.item2Price, params.item3Price].join(",")
f.save()
}
Really all you're trying to do is join your parameters from your page into one string, right?
Now this actually seems like bad design to me. What happens if the order changes, or if nothing is selected for item 2? Or what happens if somebody wants to edit your object and you need to parse the values back out? Obviously you could split on commas...until one of the values contains a comma!
You're better off storing one value for each field that means something different, or storing a single field as a structured value. You might want to look at encoding a Map into JSON and storing that, for example, if you really just want to have one field in your domain object.

Related

grails: how to properly edit/update a collection?

I just wasted half a day trying to figure this out, reading about some workarounds, and thinking "it can't be that bad - there must be a straightforward to do edit a collection in Grails, whethere using scaffolded views or my own."
Let's say I have this domain object:
class TreeGroup {
String name
List<Tree> trees
static hasMany = ['trees': MyTree]
}
Just to explain the choice of data structure - I need my records to be unique, but in the order I set. That's why I chose List, AFAIK one cannot rely on order in a Set. So there are 2 pieces to this question - 1) how to remove from any Collection, for example a Set, 2) is List the best replacement for Set in this context (preserving order).
I want to be able to create a group record with no trees in it and make 4 updates:
edit/save
edit the group record to reference 2 trees A and B
add another tree C
remove A
remove B and C
And obviously, I want the desired state after every step. Currently though, I can only add records, and if I even edit/save to list, the list elements are added to it again.
I am using the multiple select tag for this. It looks like this:
<g:select name="trees" from="${allTrees}" optionKey="id"
multiple="true" class="many-to-many"
value="${trees ? trees*.id : treeGroupInstance?.trees*.id}" />
and that's fine, in the sense that it generates an HTTP header with these variables on update:
_method:PUT
version:19
name:d5
trees:1
_action_update:Update
But the data binder only adds new elements, it never lets you edit a list.
What is the cleanest way to do it ? Is it me, not reading something obvious, or is this a design flaw of grails data binding (and of so, when/how will it be fixed) ?
Is there a way perhaps via a hidden HTTP parameter to clear the list before (re)adding elements ?
Thanks
I ended up doing this:
private repopulate(def domainObject, String propertyName, Class domainKlaz) {
if (params[propertyName] != null) {
domainObject[propertyName].clear()
domainObject[propertyName].addAll(
params[propertyName].collect { domainKlaz.get(it) }
)
}
}
and I am calling it in update controller method before save(), for every collection. OMG how ugly.

Array in view mvc

I have an array of bytes in my model
public byte[] created_dt { get; set; }
It represents a timestamp value in the database.
In my view , I am referring it as #model.created_dt
but it is coming as system.byte[]
How to resolve this?
Try as this is just an example to achieve the functionality
#foreach(var a in model.created_dt){
<label>#a</label>
}
Judging by the behavior, this looks like ASP.NET and you are simply seeing the output of an implicit call to ToString() on the array (the default way of displaying anything that does not have a template defined). You will have to do something with the raw byte data and present it to the user.
Since you refer to "timestamp" and the property name might suggest a record creation time, you may want to write a helper method to translate this raw data to a DateTime which you could then format accordingly.
However, one of the following is most likely true:
It strikes me as odd that you are using raw binary to store what should otherwise be a datetime2 column. (Or it is a datetime in your database but you're doing something unorthodox to retrieve the value.)
Your property/column name of "created_dt" is a misnomer and it is really a timestamp (i.e. rowversion) column. In which case I don't think this is something a user would know what to do with, and it probably doesn't belong on the UI.

How to pass a map from gsp to controller as part of params in Grails remoteFunction

I am trying to send map from gsp to controller but the map is considered as a string in the controller
<g:remoteFunction
action="updateCart"
params="{startDate:stDt,endDate:endDt,cartId:pkid,shoppingCart:'${shoppingCart}'}"
update="resourcesSelectedId"/>
Here the shoppingCart is a grails map variable I am trying to send
Edit:
there was a typo in the code I posted above. Missed starting "{" in the params
params="{startDate:stDt,endDate:endDt,cartId:pkid,shoppingCart:'${shoppingCart}'}"
Updated my question as per my comments below
In my case shoppingCart is an object and it has, lets say for example, items and quantity of each item. I have some rules to be applied based on the items selected and quantity and determine the price for each item and show it back to the user. I want to do this processing the controller. Whenever user updates the cart I need to re-calculate and show it back to user. Is there any other better approach you would suggest to do this instead of passing the objects back and forth
Anytime you're using the params attribute, it has to be in the format of a Map anyway, which means including the [ ]. This also means you can exclude the ${ } from any values because grails will parse all these as potential variables.
<g:remoteFunction
action="updateCart"
params="[startDate:stDt,endDate:endDt,cartId:pkid,shoppingCart:shoppingCart]"
update="resourcesSelectedId"/>
However, keep in mind that you can't send objects. I'm not sure what shoppingCart is in your example, but it would only be able to be a simple value that can be represented as a String. Possibly you would want shoppingCart.id? Otherwise, that should get you going in the right direction.
I could able to overcome this issue by following below steps
converted the shoppingcart object to json string
Pass the json as part of the params
parse the json string server-side & process
pass the updated object back to gsp

Select Multiple, get selected values and non-selected values

I have a select multiple on my page. The user can add elements to the list and remove them selecting one or more.
When I get the select's value through params.selectName, I receive only the selected ones. I
understand that this is the default behavior, but I need all of them, not only selected elements.
I don't really want to select all elements each time I send data to server. Does anyone have a better solution? Thanks.
The approach taken by the <g:checkBox> tag is to create a hidden field with the same name as the checkbox but with an underscore prepended. You could use a similar trick here, i.e. whenever you add a new <option> to the <select> you also add a hidden field named (say) selectName_options with the same value. Then in the controller you can take the difference between params.list('selectName') and params.list('selectName_options') to get the un-selected options from the list.
This is a bit of a complex solution to what should be a simple problem, but in my current project we just had the same problem and solved it as #cdeszaq describes.
Assuming an object of class Foo with a collection (bars) of Bar items, where each Bar has a String name and outputs it as its toString() representation, we do this in the FooController:
def removedItems = fooInstance.bars.findAll {
!params.bars.collect { it.key }.contains(it.name)
}
if(removedItems){
removedItems.each {
fooInstance.removeFromBars(it)
}
}

rails 3, how can a reference to fieldname pull data from another source if field is empty?

In my app, users have one "template" record (in Template table) that sets defaults for their data.
Then they create multiple records in (Userdata table).
For each Userdata record, if they enter data into a field, the app uses THAT data (of course). But if Userdata.foo is empty I'd like to use Template.foo instead, transparently. And if both are empty, then it's "empty".
I'm pretty sure the right answer is NOT to code every single place I use every field:
if Userdata.foo.blank?
Template.foo
endif
And I assume it's a matter of somehow defining my model to redefine the fieldname somehow?
And I'm hoping there's some way to not even have to code the model method field-by-field, to basically say "if the field in UserDayta is blank, use the one in Template instead..."
You can define a method in your User model like so:
def fetch_attribute(att)
if self.userdata[att].nil? and self.template[att].nil?
return nil
elsif self.userdata[att].nil?
return self.template[att]
else
return self.userdata[att]
end
end

Resources