grails runtime calculation in gsp page - grails

In my grails project I have an Invoice domain class. In this class I have amount value, discount, VAT etc. Discount and VAT are represented with two select.
In gsp I've added another field, called total, that shows the final value of the invoice. I would like that, when user changes value of discount, or of VAT, the total value changes.
For similar issue I've used a remoteFunction that, after passing parameters to a controller method, updates via javascript the value of the amount but in this case I don't know how to refer current values selected in gsp by user.

given the form with some fields in your GSP:
<g:textField name="discount" value="${discount}"/>
<g:textField name="vat" value="${vat}"/>
you can use a function like this (in jquery) to pass and receive the data to the controller:
function send(){
$.ajax({
url:'${createLink( controller:'your_controller', action:'someAction' )}',
data:{ discount:$( '#discount' ).val(), vat:$( '#vat' ).val() }
}).done( function( data ){
console.info( data );
} );

Related

Stimulus not geting values from html

I'm doing a basic controller and trying to get data from the HTML with the tag value.
The problem is that the data is always empty
<div data-controller="selectable">
<div class="flex" data-selectable-iconurl="test" data-selectable-iconurl-value="test">
something here
</div>
</div>
Notice I did multiple combinations of the value tag ( from different posts) in order to verify if one is working.
Now when I try to access the values in the controller is always empty
// selectable_controller.js
import {Controller} from "#hotwired/stimulus"
export default class extends Controller {
static values = {iconurl: String }
connect() {
console.log(this.iconurlValue)
}
}
I double-checked the documentation and could not find why the value is not passed to the controller and is always empty
When Stimulus controller is on the same element as the value, you should be able to retrieve the value:
<div data-controller="selectable" data-selectable-iconurl-value="test">
If your value needs to be set on a child element, then I suggest to just access it the old way :
console.log(this.element.querySelector("div").dataset.selectableIconurlValue)
Though your value may just be treated like a common JS dataset component. You lose every Turbo goodness such as a mutation observer to the value : https://dev.to/borama/stimulus-2-0-value-change-callbacks-what-are-they-good-for-4kho
Not sure why the required location of the value is not precised in the Stimulus Handbook. Maybe I am wrong too and there is a way to have it acknowledged by Stimulus...

Setting domain class property values with GORM

After a user creates a record in my Grails application it takes that information and populates and displays a graph. The user can then click a button on that page and be redirected to the create page. When that happens I would like the previous data entered to be displayed as the defaults for those fields.
In my controller right now we instantiate the domain class.
def create() {
[apiInstance: new Api(params)]
}
Let's say the Api class contains two properties, a string called name and an integer called myValue.
What do I need to do to show the latest values of name and myValue in the database as the new defaults for the fields in the create page?
It sounds like you just want to display each field's value?
<g:textField name="name" value="${apiInstance.name}" />
<g:textField name="myValue" value="${apiInstance.myValue}" />
If you want to display the last created Api by default, you have to get that in your controller. You can use last() to get the last created instance of a domain class.
def create() {
[apiInstance: Api.last() ?: new Api(params)]
}

Grails - remoteField with additional parameters (3 parameters, no id work around)

In a work around I've used in the past, I've used the id field to pass an additional parameter that I needed. But I need to pass three parameters through a remoteField and now am presented with the fact I need to find a way to pass these parameters:
<g:remoteField action="updateFields" update="theDiv" id-"${personInstance.id}" paramName="search" name="updateFields" value="" />
Need: The search field (search), the person id (id), and now I need the company the person works for (c_id).
I can do something like this:
<g:remoteField action="updateFields" update="theDiv" id-"${personInstance.id}" paramName="search" name="updateFields" value="" params="${[c_id:c_id, search:/'+this.value+/']}"/>
If I try to obtain the search value with the params, the search field is now '+this.value+'. Can I just pass the object search field as an addition param in the map (like above) by referencing this.value? If so, what am I doing wrong, since my gsp doesn't load.
Edit
My current work around is to tie both IDs in a ID field, split by a delimiter and then broken into an array once it reaches the controller (obviously not ideal!)
Although I don't use remoteField, I do use remoteFunction frequently and have found I can use multiple javascript based variables directly with the 'params' parameter. E.g.
<script>
function someJSFunction(id1,id2,id3) {
<g:remoteFunction action="ajax_function" params="{id1:id1,id2:id2,id3:id3}" update="someDiv"/>
}
</script>
Hope that helps.

How to use Telerik MVC Grid for brand new data (as child of one-to-many relationship)?

I have the following entities:
create table Person (
Id int primary key identity,
Name varchar(80) not null
)
create table Contact (
Id int primary key identity,
PersonId int not null foreign key references Person(Id),
Name varchar(80) not null,
Relationship varchar(80) not null,
Phone varchar(80) not null,
Email varchar(80) not null
)
I would like to make a form in ASP.NET to add a brand new person and their contacts all at once, using a textbox for the person’s name and Telerik MVC Grid for the contacts. E.g.,
<%= Html.TextBoxFor(person => person.Name) %>
<%= Html.Telerik().Grid<EditableContact>() %>
However, since the person entity is not yet created until the form is submitted, how can Telerik Grid send data to the server when a contact record is added, edited, or deleted?
Ideally, I would like to have everything (person’s name and all of their contacts) sent to the server upon submission of the form.
Should I do something like Session["UnsavedPerson"] = new Person(); when the view for the add-new-person-and-their-contacts page gets called?
There are a few ways you could accomplish this. One way I might suggest is to use create a client-side representation of the complete model you wish to save, which would be basically a JSON representation of your model.
You could then use server binding for the data source (since it sounds like you would not actually be binding to anything yet), then add a client event handler for the OnSave event. In that event, you can get the values they entered, and map them to a JSON instance of the contact model.
Then, when you click some save button, you could submit that JSON model to an AJAX method to actually save your whole model.
<%= Html.Telerik()
.Grid<EditableContact>()
.Events(events => events.OnSave('contacts_OnSave')
// rest of your grid configuration
.Render();
%>
<script type="text/javascript">
var model = {
Name:'',
// etc.
Contacts = []
};
function contacts_onSave(e) {
model.Contacts.push(e.values);
e.preventDefault(); // prevent the grid from trying to post the new record, since we'll handle it later
}
$(function() {
$('form').submit(function(e) {
model.Name = $('#Name').val();
$.post('url/to/save', model, function() { alert('Saved successfully!'); });
});
});
</script>
This, of course, is a rather crude example that could be optimized better, but I want to illustrate the idea of grabbing the values they inserted from the grid and using them later. You could certainly have the OnSave handler create a bunch of hidden inputs to make this page more POST compatible and allow you to make use of $.fn.serialize, but I leave that to you.

Model Binding to Multiple Types with Same Property Names

I have a view that contains 2 list boxes: Audience & Locale
I'm trying to submit a form that contains the selected index of both to my controller, which has an action method of this signature:
public JsonResult Submit(Audience aud, Locale loc)
{
// do stuff
}
The problem I'm having is both Audience & Locale have an ID property, so the Model Binder is a little bit confused over which to assign the selected values to. Both get assigned the value '1', when Audience should have '2' and Locale should have '1'
The question is how can I get the page to differentiate between the two when it's submitting? We've tried prepending the ID value for Locale with "locale.", so the parameter string that gets passed as data to the Controller looks like
"&locale.id=1&audience.id=2" but that doesn't seem to work.
Any suggestions? If more info is needed, I'll supply it.
Thanks
Dave
Use:
public JsonResult Submit([Bind(Prefix = "audience")]Audience aud,[Bind(Prefix = "locale")]Locale loc)
{
// do stuff
}
Every Audience field should have "audience" prefix in name in html field: audience.id,audience.name,...
<input id="audience_name" name="audience.Name" type="text" value="" />
You should have a specific ViewModel for taking data into your Submit Action. That object should have AudienceId and LocaleId. When you create your dropdowns you should create them with names that match what you expect.

Resources