grails: remoteFunction with multiple select - ajax

I need to use the remoteFunction directive with a multiple select.
The select is as follows:
<g:select name="receiptItems" from="${myproject.ReceiptItem.list()}"
multiple="multiple" optionKey="id" optionValue="description" size="5"
value="${receiptInstance?.receiptItems*.id}" class="many-to-many"
onchange="${remoteFunction(
controller: 'Receipt',
action: 'sumReceiptItems',
params: '\'receiptItemsSelected=\' + this.value',
onSuccess: 'updateTotalAmount(\'totalAmount\', data, \'00000\')')}"/>
I have the sumReceiptItems action in the Receipt controller that takes the parameter receiptItemsSelected and use it to update another text field.
The problem is that this.value gives me only one selected value, that is the last one selected. I need to pass to controller all the selected values in the select.
How can I do it?
Thanks for your precious help

Just use jQuery's val() instead of this.value, that will get all the selected items:
params: '\'receiptItemsSelected=\' + jQuery(this).val()'
Note that you have to import jQuery if you haven't used it in your project yet. You can do that simply using <r:require module='jquery' /> in the <head> section if you are using an up-to-date Grails version.

You can use JQuery to get the values:
var selections = new Array();
$("#receiptItems").change(function() {
var value = $(this).val();
selections[selections.length] = value;
});
You can add the value to a global defined list. In this way you get all the selections.

Related

Kendo MVVM Dropdown - How to set initial value based on other data?

I have the following html for a Kendo MVVM DropDownList:
<select id="responseTypeDDL"
data-role="dropdownlist"
data-text-field="SystemResponseTypeCode"
data-value-field="SystemResponseTypeId"
data-bind="value: selectedSystemResponseTypeCode, source: responseTypes">
</select>
This is my view model:
SC.ViewModels.Reference.ResponseTypeDataSource.read();
var responseTypeDDL = kendo.observable({
responseTypes: SC.ViewModels.Reference.ResponseTypeDataSource,
selectedSystemResponseTypeCode: null,
setSelectedSystemResponseTypeCode: function (code) {
this.selectedSystemResponseTypeCode = code;
},
});
kendo.bind($("#responseTypeDDL"), responseTypeDDL);
// after reading data, I call the method to set the selected value like this:
self.ResponseTypeDDL.setSelectedSystemResponseTypeCode(results.code);
The ResponseTypeDataSource.read() method returns a list of "XML", "JSON". This is the SystemResponseTypeCode field. I also read another data item from the database
and check its response type. Let's say it is "JSON". How do I set the drop down to have "JSON" selected?
First of all this part seems to be wrong
setSelectedSystemResponseTypeCode: function (code) {
this.selectedSystemResponseTypeCode = code;
},
You should make sure to call set() method while modifying an observed variable, otherwise it might not update the bindings:
this.set("selectedSystemResponseTypeCode", code);
And for your actual question
You need to set data-value-primitive="true" in order to work with just the id (Kendo Docs) (Please note changes below, value: selectedSystemResponseTypeId)
<select id="responseTypeDDL"
data-role="dropdownlist"
data-text-field="SystemResponseTypeCode"
data-value-field="SystemResponseTypeId"
data-value-primitive="true"
data-bind="value: selectedSystemResponseTypeId, source: responseTypes">
</select>
SC.ViewModels.Reference.ResponseTypeDataSource.read();
var responseTypeDDL = kendo.observable({
responseTypes: SC.ViewModels.Reference.ResponseTypeDataSource,
selectedSystemResponseTypeCode: null,
selectedSystemResponseTypeId: null,
setSelectedSystemResponseTypeId: function (id) {
this.set("selectedSystemResponseTypeId", id);
},
});
kendo.bind($("#responseTypeDDL"), responseTypeDDL);
// Get your id
var id = ...
responseTypeDDL.setSelectedSystemResponseTypeId(id);
Working example: http://dojo.telerik.com/AbIm/8
I've managed to manually set the value in dropdownlist without resorting to
data-value-primitive="true"
because i need to access the selected value and display other fields.
Here's the solution:
var id = 1004;
var dataItem = responseTypeDDL.responseTypes.get(id); //get the id in your datasource
responseTypeDDL.set("selectedsystemResponse", dataItem);

Can one avoid multiple DOM elements with same id, when using Backbone/Marionette view instances?

When I create multiple view instances of the Marionette view which is linked with a template html with ids, these would get duplicated for multiple instances of these views.
While it works correctly, I feel that there ought to be more architecturally correct way of doing this.
The example code is like below.
Template:
<script id="myTemplate" type="text/template">
<div id="myDiv">
<input type="text" id="myText"/>
<input type="button" id="myBtn" value="Click me!"/>
</div>
</script>
View:
MyView = Backbone.Marionette.ItemView.extend({
template: '#myTemplate',
events: {
'click #myBtn' : 'myFunc' //Correctly identifies its own 'myBtn'
},
myFunc : function() {
alert($('myText').val()); //Again, picks own 'myText'
}
});
var v1= new MyView();
v1.render();
var v2= new MyView();
v2.render(); //Duplicate IDs now present in DOM
I need some unique identification of these DOM elements and hence the ids.
Even when tying the model to this view, we need some way to identify these DOM elements.
What is the correct way of doing this without duplicating the ids.
Just pass the id to the view when you create it:
Template:
<script id="myTemplate" type="text/template">
<input type="text" class="js-myText"/>
<input type="button" class="js-myBtn" value="Click me!"/>
</script>
View def:
MyView = Backbone.Marionette.ItemView.extend({
template: '#myTemplate',
events: {
'click #myBtn' : 'myFunc' //Correctly identifies its own 'myBtn'
},
myFunc : function() {
alert($('myText').val()); //Again, picks own 'myText'
}
});
Instanciation:
var v1= new MyView({ id: "view" + number});
v1.render();
Then you can provide dynamic id values for your views (e.g. by using a model id).
That said, when using Marionette you shouldn't need to call render: you should instead show a view within a region. Take a look at the free sample to my Marionette book to get you up to speed.
If you must go for unique IDs to make sure no one accidentally duplicates a class name inside a view, you can use:
Underscore's uniqueId method to generate a unique ID for each DOM element inside the view, like: <input type="text" id= <%= _.uniqueId("myText_") %> /> This will just make sure that IDs are not duplicated. But they're not very helpful if you need to identify the elements by these IDs.
Marionette's TemplateHelpers which allow you to use helper functions from inside the templates:
//Define this inside your view:
templateHelpers: function() {
var that = this;
return {
getIdSuffix : function() { return that.idSuffix; }
/*Where idSuffix is passed to the view during instantiation
and assigned to this.idSuffix */
};
}
//In the template:
<input type="text" id= <%= "myText_" + getIdSuffix() %> />
You now know before runtime what DOM IDs you will have, provided care is taken not to give the same idSuffix to more than one view instance.
Simply put, don't use an id if it's not unique. Use a class or some other way of identifying the element.
You can use any jQuery selector to locate the element you want, ranging from the insane and brittle:
this.$('div > input:first'); // don't actually do this!
to the slower but semantically better:
this.$('[data-element-type="some-text-box-descriptive-name"]');
Although in reality, using a class is best, because that's what a class is for - for identifying a type of element. I can see that a maintainer might not know not to change your class in the template, so a data-attribute might be acceptable, or maybe even (in this case):
this.$('input[type=text]');

How to retrieve value of a kendoAutocomplete textbox without using id, $(element) and only using custom bindings

I have the following code:
// KendoAutocomplete textbox
<input id="search" data-bind="kendo: 'kendoAutoComplete', source:searchSource" />
// For now
var autoComplete = $("#search").kendoAutoComplete();
var x= autoComplete.data("kendoAutoComplete").value();
How can I retrieve the value for x using custom binding without using id?
Your question is a little bit confusing. Lets see if I guess what you mean by "retrieve the value for x using custom binding".
Problem statement: Define a KendoUI AutoComplete that when enter a value automatically updates an ObservableObject so I can get the value without having to use autoComplete.data("kendoAutoComplete").value();
Start defining the input as:
<input id="search" data-role="autocomplete" data-bind="source: searchSource, value: x"/>
Where I define what is the datasource for autocomplete element (searchSource) plus, where to store that introduced value (x).
Then, in JavaScript I do:
var ds = new kendo.data.DataSource({
data: [ "option1", "option2", "option3" ]
});
var obj = kendo.observable({ searchSource: ds, x: "option2" });
kendo.bind("body",obj);
Where ds is the DataSource containing the values for the autocomplete and it is bound to the body of your HTML element (or whatever portion of your document).
Whenever I want to get the value introduced in the autocomplete I simple use obj.x.
You can even get an HTML div magically updated doing:
<div data-bind="html: x"></div>
See running example here: http://jsfiddle.net/OnaBai/twznn/

Custom grid button to load ajax content depending on selected row

I need to make a custom buttom in my grid that will open a modal which will render a select field with options depending on selected row.
So the user will select a row and click the button. The row id should be passed as an url parameter to my action so that it can make a query and populate the select field.
This is where I'm struggling:
navigatorExtraButtons="{
honorarios:{
title: 'Consultar honorários do processo',
caption: 'H',
icon: 'none',
onclick: function(){
var id = jQuery('#processoTable').jqGrid('getGridParam','selrow');
if (id) {
var ret = jQuery('#processoTable').jqGrid('getRowData',id);
// need to pass ret.nrProcesso as param to the URL that will load content into the modal
} else { alert('Please select a row.');}
}
},
With above code I can get the desired ID value from selected row. But I don't know how to assign it to a
<s:url... param
and populate a modal...
Thanks in advance.
I've found a solution. Posting here hoping it might help someone else.
I've ended up using plain old jquery script to get the modal to show up instead of jquery-plugin.
Just construct your action url adding desired parameter and call an ajax function:
<sj:submit id="consulta_honorarios" value="Consultar Honorários" onClickTopics="honorarios" button="true"/>
<sj:dialog
id="mydialog"
title="Consultar honorários"
autoOpen="false"
modal="true"
dialogClass="ui-jqdialog"
/>
<script type="text/javascript">
jQuery(document).ready(function(){
jQuery("#consulta_honorarios").click(function(){
var actionURL = '<s:property value="%{advprocselecturl}" />';
var id = jQuery('#processoTable').jqGrid('getGridParam','selrow');
if (id) {
var ret = jQuery('#processoTable').jqGrid('getRowData',id);
actionURL += '?nrProcesso=' + ret.nrProcesso;
// alert('id='+ret.nrProcesso+' / actionURL='+actionURL);
jQuery.ajax({
url: actionURL
}).done(function(data){
jQuery('#mydialog').html(data).dialog('open');
});
} else {
jQuery('<div />').html('Por favor, selecione um registro.').dialog();
}
});
});
In your action you must declare a variable with the same name as your url parameter (nrProcesso in my case) with respective getter and setter.

How to pass both model value & text value to controller in mvc?

I want to pass two values from view to controller . i.e., #Model.idText and value from textbox. here is my code:
#using HTML.BeginForm("SaveData","Profile",FormMethod.Post)
{
#Model.idText
<input type="text" name="textValue"/>
<input type="submit" name="btnSubmit"/>
}
But problem is if i use "Url.ActionLink() i can get #Model.idText . By post action i can get textbox value using FormCollection . But i need to get both of this value either post or ActionLink
using ajax you can achieve this :
don't use form & declare your attributes like this in tags:
#Model.idText
<input type="text" id="textValue"/>
<input type="submit" id="btnSubmit"/>
jquery:
$(function (e) {
// Insert
$("#btnSubmit").click(function () {
$.ajax({
url: "some url path",
type: 'POST',
data: { textField: $('#textValue').val(), idField: '#Model.idText' },
success: function (result) {
//some code if success
},
error: function () {
//some code if failed
}
});
return false;
});
});
Hope this will be helpful.
#using HTML.BeginForm("SaveData","Profile",FormMethod.Post)
{
#Html.Hidden("idText", Model.idText)
#Html.TextBox("textValue")
<input type="submit" value="Submit"/>
}
In your controller
public ActionResult SaveData(String idText, String textValue)
{
return null;
}
I'm not sure which part you are struggling with - submitting multiple values to your controller, or getting model binding to work so that values that you have submitted appear as parameters to your action. If you give more details on what you want to achieve I'll amend my answer accordingly.
You could use a hidden field in your form - e.g.
#Html.Hidden("idText", Model.idText)
Create a rule in global.asax and than compile your your with params using
#Html.ActionLink("My text", Action, Controller, new { id = Model.IdText, text =Model.TextValue})
Be sure to encode the textvalue, because it may contains invalid chars
Essentially, you want to engage the ModelBinder to do this for you. To do that, you need to write your action in your controller with parameters that match the data you want to pass to it. So, to start with, Iridio's suggestion is correct, although not the full story. Your view should look like:
#using HTML.BeginForm("SaveData","Profile",FormMethod.Post)
{
#Html.ActionLink("My text", MyOtherAction, MaybeMyOtherController, new { id = Model.IdText}) // along the lines of dommer's suggestion...
<input type="text" name="textValue"/>
<input type="submit" name="btnSubmit"/>
#Html.Hidden("idText", Model.idText)
}
Note that I have added the #Html.Hidden helper to add a hidden input field for that value into your field. That way, the model binder will be able to find this datum. Note that the Html.Hidden helper is placed WITHIN your form, so that this data will posted to the server when the submit button is clicked.
Also note that I have added dommer's suggestion for the action link and replaced your code. From your question it is hard to see if this is how you are thinking of passing the data to the controller, or if this is simply another bit of functionality in your code. You could do this either way: have a form, or just have the actionlink. What doesn't make sense is to do it both ways, unless the action link is intended to go somewhere else...??! Always good to help us help you by being explicit in your question and samples. Where I think dommer's answer is wrong is that you haven't stated that TextValue is passed to the view as part of the Model. It would seem that what you want is that TextValue is entered by the user into the view, as opposed to being passed in with the model. Unlike idText that IS passed in with the Model.
Anyway, now, you need to set up the other end, ie, give your action the necessary
[HttpPost]
public ActionResult SaveData(int idText, string textValue) // assuming idText is an int
{
// whatever you have to do, whatever you have to return...
}
#dommer doesn't seem to have read your code. However, his suggestion for using the Html.ActionLink helper to create the link in your code is a good one. You should use that, not the code you have.
Recapping:
As you are using a form, you are going to use that form to POST the user's input to the server. To get the idText value that is passed into the View with the Model, you need to use the Html.Hidden htmlhelper. This must go within the form, so that it is also POSTed to the server.
To wire the form post to your action method, you need to give your action parameters that the ModelBinder can match to the values POSTed by the form. You do this by using the datatype of each parameter and a matching name.
You could also have a complex type, eg, public class MyTextClass, that has two public properties:
public class MyTextClass
{
public int idText{get;set}
public string TextValue{get;set;}
}
And then in your controller action you could have:
public ActionResult SaveData(MyTextClass myText)
{
// do whatever
}
The model binder will now be able to match up the posted values to the public properties of myText and all will be well in Denmark.
HTH.
PS: You also need to read a decent book on MVC. It seems you are flying a bit blind.
Another nit pick would be to question the name of your action, SaveData. That sounds more like a repository method. When naming your actions, think like a user: she has simply filled in a form, she has no concept of saving data. So the action should be Create, or Edit, or InformationRequest, or something more illustrative. Save Data says NOTHING about what data is being saved. it could be credit card details, or the users name and telephone...

Resources