Kendo Grid Inline MultiSelect - Posted Values - kendo-grid

I'm replicating the functionality very close to what's seen here. https://onabai.wordpress.com/2013/07/17/kendoui-multiselect-in-a-grid-yes-we-can/
I have Kendo grid with an inline multiselect editor field. I have a datasource.sync() event kicked off on change of that multiselect. The issue I'm having is how the data is arranged in the post variables.
I'm using FireBug in FireFox. I can set a function to view the values in my multiselect field like this at the sync() event.
console.log(this.value());
This would be for a string array field I have called "RoleCode". Anyway, the console log displays the values as they should, for example
A, OU
However, when I look in the Post call to my controller and at the parameters, I see the RoleCode field is duplicated, which is why my controller doesn't recognize the method signature. For example, this is what I see in FireBug...
ID 123
Field1 TextFromField1
RoleCode[1][RoleCode] OU
RoleCode[] A
Any idea how I should set this up so the post parameters are usable?
UPDATE
For now I just altered the update function to send the multiselect values as a comma separated string. I can deal with them in the controller. I don't really like this setup, but until I find how to get the posted values to send correctly, this is what I'm going with.
update: {
url: "Home/GridUpdate",
type: "POST",
dataType: "json",
data: function () {
//Grid does not post multiselect array correctly, need to convert to a string
var rolesString = $("#gridRoleList").data("kendoMultiSelect").value().toString();
return { rolesString: rolesString };
},
complete: function (e) {
setTimeout(function () {
refreshGrid();
}, 300);
},
success: function (result) {
// notify the data source that the request succeeded
options.success(result);
},
error: function (result) {
// notify the data source that the request failed
options.error(result);
}
},
UPDATE 2
Actually that's not a good idea because if I edit another field in the grid, I get a js error because the multiselect is not found.

Looks like your issue can be resolved by sending the data after serializing it
Read action - using MVC Wrapper
.Create(create => create.Action("Create", "Home").Data("serialize"))
JS Code
<script type="text/javascript">
function serialize(data) {
debugger;
for (var property in data) {
if ($.isArray(data[property])) {
serializeArray(property, data[property], data);
}
}
}
function serializeArray(prefix, array, result) {
for (var i = 0; i < array.length; i++) {
if ($.isPlainObject(array[i])) {
for (var property in array[i]) {
result[prefix + "[" + i + "]." + property] = array[i][property];
}
}
else {
result[prefix + "[" + i + "]"] = array[i];
}
}
}
</script>
Please refer here for complete source code

Here's how I solved it. On the change event of the editor function, I updated the value of the model with the value of the multiselect. Then the data posts correctly as a string array like this.
ID 123
Field1 TextFromField1
RoleCode[] A
RoleCode[] OU
My grid editor function
function roleMultiSelectEditor(container, options) {
$('<input id = "gridRoleList" name="' + options.field + '"/>')
.appendTo(container)
.kendoMultiSelect({
dataTextField: "RoleCode",
dataValueField: "RoleCode",
autoBind: true,
change: function (e) {
//Applies the value of the multiselect to the model.RoleCode field
//Necessary to correctly post values to controller
options.model.RoleCode = this.value();
processGridMultiSelectChange();
},
dataSource: {
type: "json",
transport: {
read: {
dataType: "json",
url: baseUrl + "api/DropDownData/RoleList",
},
}
},
dataBound: function (e) {
}
});
}

Related

How to utilize a value from the response of one .AJAX function in another as a parameter to insert into the POST request

I'm trying to use a value received from the response in one ajax function as a parameter in another ajax function call in an html file.
I'm sorry if this is very basic, but I'm very new at this.
I've tried to call the value the same as I do in the body of the HTML and many other attempts.
1 - Here is the initial call (working):
$.ajax({
"url":api_base+"/endpoint_01",
"type":"GET",
"contentType":"application/json",
"success":function(data){
var data = data[0];
$('#dash_value').html(data.value);
}
});
2 - Here is how I access this in html (:
<div class="highlighted-text" id="dash_value"></div>
3 - I don't know how to utilize this later in the file:
function function_02(){
$.ajax({
"url":api_base+"endpoint_02?value=" + dash_value,
"type":"POST",
"beforeSend":function(){
$('#button_01').prop('disabled', true);
},
"dataType":"text",
"success":function(data){
swal(data, {
icon : "success",
buttons: false,
timer: 3000
});
},
"complete":function(){
$('#button_01').prop('disabled', false);
}
});
}
the POST should be sent like this:
https://endpoint02?value=dash_value
but I'm getting everything except that. Please help.
Try declaring a variable outside the scope of the Ajax method so code outside the method can access it later then assign the variable to the returned data inside the ajax scope:
var outerScopeData = "";
$.ajax({
"url":api_base+"/endpoint_01",
"type":"GET",
"contentType":"application/json",
"success":function(data){
var data = data[0];
// add this here:
outerScopeData = data.value;
$('#dash_value').html(data.value);
}
});
You need to define the dash_value before you make the second ajax call.
function function_02(){
const dash_value = $("dash_value").data()
$.ajax({
"url":api_base+"endpoint_02?value=" + dash_value,
"type":"POST",
"beforeSend":function(){
$('#button_01').prop('disabled', true);
},
"dataType":"text",
"success":function(data){
swal(data, {
icon : "success",
buttons: false,
timer: 3000
});
},
"complete":function(){
$('#button_01').prop('disabled', false);
}
});
}

parameter passing from CDE to PDI pentaho

I have a scenario to pass parameters from pentaho cde using kettle to pentaho data integration and then update the table using the passed parameter in PDI. How can i pass the parameter and get the passed parameter in PDI?
Thanks in advance!!!
You will need to use the Pentaho plugin builder, SPARKL.
With it you can upload a transformation as a callable endpoint and use a CDE dashboard to call it.
First of all, you need a transformation that expects parameters. You can try it with a test one before going to a more advanced transformation:
Example:
defining a parameter and fetching with a Get Variables step
Second you will create a new plugin on SPARKL.
Sparkl welcome screen
Give your plugin a name and add a kettle endpoint to it. If you now look at your pentaho-solutions/system folder, you will have a new folder with the plugin name. Open it and find the ktr file inside the subfolders to replace it with your transformation.
The last step is to add a new dashboard to your plugin and edit it. If you go to the datasources tab now, notice the datasources with 'endpoint' in the name. We will access them by code, but is good to know they are here so you can read data from it too, not just input data.
add a new resource of javascript to your CDE layout with the following code:
var myPluginName = {};
(function(myself) {
myself.runEndpoint = function (pluginId, endpoint, opts) {
if (!pluginId && !endpoint) {
Dashboards.log('PluginId or endpointName not defined.');
return false
}
var _opts = {
success: function () {
Dashboards.log(pluginId + ': ' + endpoint + ' ran successfully.')
},
error: function (){
Dashboards.log(pluginId + ': error running ' + endpoint + '.')
},
params: {},
systemParams: {},
type: 'POST',
dataType: 'json'
}
var opts = $.extend( {}, _opts, opts);
var url = Dashboards.getWebAppPath() + '/plugin/' + pluginId + '/api/' + endpoint;
function successHandler (json) {
if (json && json.result == false) {
opts.error.apply(this, arguments);
} else {
opts.success.apply( this, arguments );
}
}
function errorHandler () {
opts.error.apply(this, arguments);
}
if (endpoint != 'renderer/refresh' ) {
var ajaxOpts = {
url: url,
async: true,
type: opts.type,
dataType: opts.dataType,
success: successHandler,
error: errorHandler,
data: {}
}
} else {
var ajaxOpts = {
url: url,
async: true,
type: 'GET',
dataType: opts.dataType,
success: successHandler,
error: errorHandler,
data: {}
}
}
_.each( opts.params , function ( value , key) {
ajaxOpts.data['param' + key] = value;
});
_.each(opts.systemParams , function (value , key) {
ajaxOpts.data[key] = value;
});
$.ajax(ajaxOpts)
}
})(myPluginName);
You can change myPluginName with whatever you want but that enables you to call that endpoint sending parameters with any button. To do so you can use that code:
myPluginName.runEndpoint(
'myPluginName', // Plugin identifier.
'endpointName', // Put your endpoint name here!
{
params: {
'EXAMPLE_PARAMETER' : foo_bar
},
success: function() { Dashboards.fireChange('refresh', 1); alert('data sent'); },
error: function() { alert('Ops, something went wrong. Check the logs.'); }
})
You can keep track of the execution by monitoring the bi-server logs.
More information on the sources:
Diethard Steiner - Blog
Francesco Corti - Blog
Follow these guys, they are amazing.
You could do that, or you could just create a CDA data source, which takes a parameter as defined in your transformation.
Params are passed to CDA via the usual &paramYOURPARAMNAME=x syntax on the URL.
In the transformation you get the parameter using the get variables step.
Did I miss something?

How to have a custom value in JSON with JQueryi UI Autocomplete?

I'm using the JQuery UI autocomplete plugin (cached version) with JQuery-UI 1.11.1
Due to some server-side changes in the JSON I am using as source, I need to adapt my code.
Here is an example of my JSON:
[{
"name": "Varedo"
}, {
"name": "Varena"
}, {
"name": "Varenna"
}, {
"name": "Varese"
}]
produced by an URL with this style:
[url]/?name=vare
Since the GET variable is different from the default one ("term"), I already adapted my code for the custom request as suggested here:
$(function () {
var cache = {};
$("#searchTextField").autocomplete({
minLength: 3,
source: function (request, response) {
var term = request.term;
if (term in cache) {
response(cache[term]);
return;
}
$.getJSON("[url]", {
name: request.term
}, function (data, status, xhr) {
cache[term] = data;
response(data);
});
}
});
});
However I need to also adapt the code in order to use a custom JSON value (the default is "value" http://api.jqueryui.com/autocomplete/#option-source) which is in my case is "name" (as you can see from the JSON).
How can I do that?
At the moment this is what I get from the autocomplete:
So I guess I am somehow giving as response JS Objects and not strings.
Thanks in advance.
Currently you're saving the response as it is into your cache object, which is not valid format for jQuery UI autocomplete. You should convert the data into proper format digestable for autocomplete.
Either you should pass an array of strings, or an array of objects having label and value properties.
Since the response only contains name properties, you can convert it into an array of strings using jQuery map() method and save it in cache variable as follows:
$("#searchTextField").autocomplete({
minLength: 3,
source: function (request, response) {
var term = request.term;
if (term in cache) {
response(cache[term]);
return;
}
$.getJSON("[url]", {
name: request.term
}, function (data, status, xhr) {
cache[term] = $.map(data, function (obj) { // returns array of strings
return obj.name
});
// return the new array rather than original response
response(cache[term]);
});
}
});

load grid on row click of another grid

I am not able to load store of one grid(Grid 2) when I click one row of another grid(Grid 1). When I click on one row it sending http request to servlet of Grid2 and In response I am getting correct data. but I am not getting that response in Grid 2 store. actually I am trying to save that response in One array from that array I am creating store to 2nd grid. below is the listener part of 1st grid:
listeners: {
'select': function(grid,record, rowIndex,e) {
var selectedvalue = record.get('YCSET_ID');
//callAjaxToCheckSession(selectedvalue);
//alert(selectedvalue);
console.log('click'+selectedvalue);
changeConnection(selectedvalue,yieldstore,records)
//yieldstore is the store for second grid and records is an array
}
now function changeConnection:
function changeConnection(selected,yieldstore,records){
alert(selected);
Ext.Ajax.request({
url: 'YieldCurveServlet', //servlet of 2nd grid
method:'GET',
headers: {
'Content-Type': 'text/html'
},
params: {
YCSET_ID: selected
},
success: function(response, opts) {
var res = Ext.decode(response.responseText);
console.dir(res); //here I am getting correct response
if(res !== null && typeof (res) !== 'undefined'){
// loop through the data
Ext.each(res.data, function(obj){
//add the records to the array
records.push({
YCSET_ID: obj.YCSET_ID,
YCSET_TENOR: obj.YCSET_TENOR,
YCSET_TENOR_UNIT: obj.YCSET_TENOR_UNIT,
YCSET_BID_RATE: obj.YCSET_BID_RATE,
YCSET_ASK_RATE: obj.YCSET_ASK_RATE
})
});
//update the store with the data that we got
yieldstore.loadData(records);
}
},
failure: function(response, opts) {
console.log('server-side failure with status code ' + response.status);
}
});
}
and below is store definition for 2nd grid:
var records = [];
var yieldstore = Ext.create('Ext.data.Store', {
fields :['YCSET_ID',
'YCSET_TENOR','YCSET_TENOR_UNIT',{
name:'YCSET_BID_RATE',
mapping :'YCSET_BID_RATE',
type: 'double'
},{
name:'YCSET_ASK_RATE',
type: 'double'
}],
data: records
});
Where I am doing wrong?
Oops a lot of weird things going on on your ExtJs code.
1.- I recommend you to use a store binded to your grid. (see official doc)
2.- Bind a model to your store.
3.- Define (if it makes sense) your own class that extends store (EmployeesStore).
4.- In order to load information in you second grid do something like:
var storeOfSecondGrid = Ext.ComponentQuery.query('grid[itemId=mySecondGrid]')[0].getStore();//where itemId is part of your grid config
storeOfSecondGrid.load({
callback:function(){
console.log('after load');
}
});

Adding StateCode dash StateName to the autocomplete using MVC4.5 and a JsonResult

I am trying to get the state code to be followed by a dash and the state name using an ajax autocomplete syntax. I'm using jQuery and jQueryUI and the jQueryUI autocomplete function to attempt this.
I am using this json result:
[{"code":"AK","name":"Alaska"},{"code":"AL","name":"Alabama"},
{"code":"AR","name":"Arkansas"},{"code":"AZ","name":"Arizona"},
{"code":"CA","name":"California"}, ... ]
And I'm using this jQuery ajax call with an embedded
$.ajax({
url: '/Cats/State/List',
type: 'POST',
dataType: 'json',
success: function (data) {
$('#Cat_stateCode').autocomplete(
{
source: data.code + '-' + data.name,
minLength: 2
});
}
});
The mvc controller JSON Result looks like this:
public JsonResult List()
{
return Json(db.States.ToList(), JsonRequestBehavior.AllowGet);
}
How do I get the auto complete to show:
CA - California
CO - Colarado
If I type out C? Or does Autocomplete only work with simple json like {"AK", "AL", "AR" ... }?
Figured it out:
$("#Cat_stateCode").autocomplete({
source: function (request, response) {
$.ajax({
url: "/Cat/States/List",
dataType: "json",
data: {
style: "full",
maxRows: 12,
req_state_part: request.term
},
success: function (data) {
response($.map(data, function (item) {
return {
label: item.code + ' - ' + item.name,
value: item.code
}
}));
// alert("data.code:" + data);
},
error: function (e) {
alert("e.error:" + e.error);
}
});
},
minLength: 1,
select: function (event, ui) {
//alert("ui item:" + ui.item ? "Selected: " + ui.item.label : "Nothing selected, input was " + this.value); //todo: remove after dev
},
open: function () {
$(this).removeClass("ui-corner-all").addClass("ui-corner-top");
},
close: function () {
$(this).removeClass("ui-corner-top").addClass("ui-corner-all");
}
});
In my mvc CatStateController I have this:
public JsonResult List(String stateAbbreviation)
{
String StateNameORStateCodeContains = Request.Params["req_state_part"];
return Json(db.States.Where(state => state.name.Contains(StateNameORStateCodeContains) || state.code.Contains(StateNameORStateCodeContains)).ToList(), JsonRequestBehavior.AllowGet);
}
So it looks like it doesn't sent the term over, it only send over some params you make up in the data element. Since you can make up pretty much anything its up to the developers imagination. One thing I was trying to do was create a closure b/c I have a lot of different animals with different states. And I need to create this same autocomplete function for each of them. So I need to ask another question how do you remove the auto complete so I can call that same function from many different ids, or do I just separate them out with a comma like so:
$("#Cat_stateCode,#Dog_stateCode,#Penguin_stateCode...").autocomplete({ ... ???
And I believe the answer to the second part is in here. I think its insinuating just add some class or attribute to the applicable input tags and then just perform an each over them and them lastly apply the autocomplete to the $(this).autocomplete immediately after each each iteration occurs.
Found a better way with just set the input tag to have a class="cssClassName". Had to use the TextBoxFor:
#Html.TextBoxFor(model => model.Cat.stateCode, new { #class = "StateCodeAutoComplete" })