Populating a grid using kendo js - javascript

I am working on a web app which needs to populate a grid with some data. I have a button wired with a onClick method which opens a new modal window for the grid to be displayed. I am using a jquery post call to the controller. However, I am unable to get the json data and assign it to my variable.
My code is as follows:
var grid_ds;
$.post('${ctx}/class/student/details?studentId=${student.studentId}', function(data){
}, 'json');
$('#student_grid').kendoGrid({
dataSource: grid_ds,
columns: [
{field: "studentName", title: "Student Name"},
{field: "studentClass", title: "Class"}
],
dataBound: function () {
emptyGrid($('#student_grid'));
}
}).data('kendoGrid');
My controller sends json back. I can see the data coming. How should I assign the json data to grid_ds and student_grid and make the values populate in the grid.

You could try using a kendo.data.DataSource with a custom transport function like so:
$('#student_grid').kendoGrid({
dataSource: dataSource = new kendo.data.DataSource({
transport: {
read: function (e) {
$.post('${ctx}/class/student/details?studentId=${student.studentId}', 'json')
.done(function (data) {
e.success(data);
});
}
}
}),
columns: [
{
field: "studentName",
title: "Student Name"
},
{
field: "studentClass",
title: "Class"
}
]});
I think the problem may be with how you're fetching the data. Since $.post is an ajax call operating out of band, grid_ds is most likely undefined when being passed to the .kendoGrid() function.
I wasn't able to locate the dataBound configuration property that you specify in your question in the kendo.ui.Grid. Do you happen to know where this configuration setting came from?

Related

Automatically create header from JSON file, Bootstrap-table

I'm working with this bootstrap library and actually everything works fine. The question is, Can bootstrap-table generate header automatically in depend of JSON file? I've tried to find any information about that, but unlucky. Now my header is generated from script like from this example:
function initTable() {
$table.bootstrapTable({
height: getHeight(),
columns: [{
field: 'field1',
title: 'title1',
sortable: true
}, {
field: 'field2',
title: 'title2',
sortable: true
}, {
field: 'field3',
title: 'title3',
sortable: true
}, {
field: 'Actions',
title: 'Item Operate',
align: 'center',
events: operateEvents,
formatter: operateFormatter
}
],
formatNoMatches: function () {
return "This table is empty...";
}
});
Does anyone how to generate header automatically?
Populating from a flat json file is definetly possible but harder than from a seperate (slimmer and preped) data request, because title and other attributes 'might' have to be guessed at.
Ill show basic approach, then tell you how to make it work if stuck with a flat file that you CAN or CANT affect the format of (important point, see notes at end).
Make a seperate ajax requests that populates var colArray = [], or passes direct inside done callback.
For example, in callback (.done(),.success(), ect) also calls to the function that contains the js init code for the table.
You might make it look something like this:
function initTable(cols) {
cols.push({
field: 'Actions',
title: 'Item Operate',
align: 'center',
events: operateEvents,
formatter: operateFormatter
});
$("#table").bootstrapTable({
height: getHeight(),
columns: cols,
formatNoMatches: function () {
return "This table is empty...";
}
});
}
$(document).ready(function(){
$.ajax({
method: "POST",
url: "data/getColumns",
// data: { context: "getColumns" }
datatype: "json"
})
.done(function( data ) {
console.log( "getCols data: ", data );
// Prep column data, depending on what detail you sent back
$.each(data,function(ind,val){
data.sortable = true;
});
initTable(data);
});
});
Now, if you are in fact stuck with a flat file, point the ajax towards that then realise the question is whether you can edit the contents.
If yes, then add a columns array into it with whatever base data (title, fieldname, ect) that you need to help build your columns array. Then use responseHandler if needed to strip that columns array if it causes issues when loading into table.
http://bootstrap-table.wenzhixin.net.cn/documentation/#table-options
http://issues.wenzhixin.net.cn/bootstrap-table/ (click 'see source').
If no, you cant edit contents, and only have the fieldname, then look at using that in the .done() handler with whatever string operation (str_replace(), ect) that you need to make it look the way you want.

Angular with Kendo, Using Grid Values Asynchronously

Ok I'm pretty sure I know exactly what I need to do here but I'm not sure how to do it. Basically I have a grid that I want to make a key column bind to an array of key/values, which I've done before with kendo (not using Angular) and I know that when I'm creating my key/value array asynchronously then that needs to complete before I can get them show-up with kendo, which I have done using promises before.
So here I have the same issue only angular is also involved. I need to fetch and format an array of data into the format in which a kendo grid column can digest it, so no problem here is my controller code:
var realm = kendo.data.Model.define({
id: 'realmID',
fields: {
realmID: { editable: false, nullable: true }
realmType: { type: 'string', validation: { required: true } }
}
})
var ds1 = kendoHelpers.dataSourceFactory('realms', realm, 'realmID')
var realmType = kendo.data.Model.define({
id: 'realmTypeID',
fields: {
realmTypeID: { editable: false, nullable: true },
name: { type: 'string', validation: { required: true } }
}
})
var ds2 = kendoHelpers.dataSourceFactory('realms/types', realmType, 'realmTypeID')
$scope.mainGridOptions = {
dataSource: ds1,
editable: true,
navigatable: true,
autoBind:false,
toolbar: [
{ name: "create" },
{ name: 'save' },
{ name: 'cancel' }
],
columns: [
{ field: 'realmID', title: 'ID' }
{ field: 'realmTypeID', title: 'Realm Type', editor: realmTypesDDL, values: $scope.realmTypeValues },
{ command: "destroy" }
]
}
$scope.secondGridOptions = {
dataSource: ds2,
editable: true,
navigatable: true,
toolbar: [
{ name: "create" },
{ name: 'save' },
{ name: 'cancel' }
],
columns: [
{ field: 'realmTypeID', title: 'ID' },
{ field: 'name', title: 'Name' }
{ command: "destroy" }
]
}
ds2.fetch(function () {
$scope.realmTypeValues = [{ text: 'Test', value: "24bc2e62-f761-4e70-804c-bc36fdeced3d" }];
//this.data().map(function (v, i) {
// $scope.realmTypeValues.push({ text: v.name, value: v.realmTypeID})
//});
//$scope.mainGridOptions.ds1.read()
});
function realmTypesDDL(container, options) {
$('<input />')
.appendTo(container)
.kendoDropDownList({
dataSource: ds2,
dataTextField: 'name',
dataValueField: 'realmTypeID'
});
}
I made this dataSourceFatory helper method above to return me a basic CRUD kendo dataSource that uses transport and also injects an authorization header which is working fine so don't get hung up on that, ultimately I'm going to be using this data in another grid as well as for reference values for the main grid, but I've hard coded some values that I can use to test with in the ds2.fetch callback.
My HTML is pretty plain:
<div>
<h2>Realms</h2>
<kendo-grid options="mainGridOptions"></kendo-grid>
<h2>Realm Types</h2>
<kendo-grid options="secondGridOptions"></kendo-grid>
</div>
This all works fine and well except I am only seeing the GUID of the realmTypeID in the grid, I click it and the editor is populated correctly so that's good but I want the text value to be displayed instead of the GUID. I'm sure the issue is that the array of values is empty whenever angular is binding to the grid options. My questions are:
How do I either delay this bind operation or manually rebind it after the fetch call?
Is there a better way to handle a situation like this? I try not to expend finite resources for no reason (IE making server calls when unnecessary)
Note: When I move the creation of the text/value array to happen before the grid options, I get the desired behavior I am after
EDIT A work around is to not use the directive to create the grid and instead defer the grid creation until the callback of whatever data your column is dependent on, I was hoping for a more elegant solution but this is better than nothing. So your HTML becomes something like
<h2>Realms</h2>
<div id="realms"></div>
<h2>Realm Types</h2>
<kendo-grid options="secondGridOptions"></kendo-grid>
Then you can create the grid in the fetch callback for example:
ds2.fetch(function () {this.data().map(function (v, i) {
$scope.realmTypeValues.push({ text: v.name, value: v.realmTypeID})
});
$('#realms').kendoGrid($scope.mainGridOptions);
$scope.mainGridOptions.dataSource.fetch()
});
But this doesn't feel very angularish so I'm really hoping for a better solution!
Ok...well I think I hacked this enough and without another suggestion I'm going to go forward with this approach. I'm just going to move the binding logic to the requestEnd event of the second grid so that the values array can be populated right before the binding even. I'm also reworking the values array in this method. It is a bit weird though, I think there is some kendo black magic going on with this array because I can't just set it to a new empty array without it breaking completely...which is why I'm poping everything out prior to repopulating the array. That way when something is deleted or edited in the second grid, the DDL in the first grid is updated in the callback.
function requestEnd(e) {
for (var i = $scope.realmTypeValues.length; i >= 0; i--) $scope.realmTypeValues.pop();
var data;
if (e.type == "read")
data = e.response;
else
data = e.sender.data();
data.map(function (v, i) { $scope.realmTypeValues.push({ text: v.name, value: v.realmTypeID }); });
if ($('#realms').data('kendoGrid') == undefined) {
$('#realms').kendoGrid($scope.mainGridOptions);
}
else
$('#realms').data('kendoGrid').columns[4].values = $scope.realmTypeValues;
}
ds2.bind('requestEnd', requestEnd);
So I'm going to accept my own answer unless anyone has a better approach!

How to provide data to Fuel UX datagrid from Rails?

I'd like to use the Fuel UX datagrid to display some data I am retrieving from my database. The page is served from a ruby on rails server.
The javascript example code for building the data object:
var dataSource = new StaticDataSource({
columns: [{
property: 'toponymName',
label: 'Name',
sortable: true
}, {
property: 'countrycode',
label: 'Country',
sortable: true
}, {
property: 'population',
label: 'Population',
sortable: true
}, {
property: 'fcodeName',
label: 'Type',
sortable: true
}],
data: sampleData.geonames,
delay: 250
});
$('#MyGrid').datagrid({
dataSource: dataSource,
stretchHeight: true
});
$('#datagrid-reload').on('click', function () {
$('#MyGrid').datagrid('reload');
});
If I am understanding the code, I am going to be defining my columns and some attributes in the columns object inside of the dataSource variable, and the data object is being loaded by sampleData.geonames.
The sampleData is here
What can I do using the rails conventions to replace the sampleData.geonames? I tried tweaking this a few ways to load rails objects in to here.
For example, I modified my columns' property fields to correspond to some properties of my User model. I tried replacing the
data: sampleData.geonames,
to
data: <%= #users.to_json %>,
I'm a little restricted on gems and versions, currently using Rails 2.3.
Thanks for any help.
If you want the datagrid to make a background AJAX request to load the data from your app, please see this tutorial which will be closer to what you need:
http://dailyjs.com/2012/10/29/fuel-ux
This would have the benefit of an immediate page load followed by asynchronous loading of data.
If you would rather stick with the StaticDataSource approach just embed a small script on your page similar to this:
<script>
var myData = { ... };
</script>
Then, load that with:
var dataSource = new StaticDataSource({
columns: [ ... ],
data: myData,
delay: 250
});

Process extjs store proxy data after data recieved

I am using extjs sencha store for storing data. I make a proxy call to a web-service to get data. I refresh the data using store.load() function.
I am looking to edit the data that is received before it is given to the grid.
I know about the load event, but this function is executed after the load is completed and data is populated with the current data.
listeners : {
'load' : function(store,records, options) {
}
},
I am looking to see how I can edit the returned data from web-service before it is assigned to the store. Basically data returned from my webservice is in different format than the format we give to extjs datagrid. So, want to do a data operation before we give to the grid. Hope we can do this.
Thx
Model mappings can help you do this. There is a conversion function that can be supplied as well. Here is the example from the docs:
Ext.define('User', {
extend: 'Ext.data.Model',
fields: [
{
name: 'firstName',
convert: function(value, record) {
var fullName = record.get('name'),
splits = fullName.split(" "),
firstName = splits[0];
return firstName;
}
},
'name', 'email',
{name: 'age', type: 'int'},
{name: 'gender', type: 'string', defaultValue: 'Unknown'}
]
});

extjs ServerProxy error on save

I'm trying to update a field value from a grid row icon. But I get this error:
Uncaught Ext.data.proxy.Server.buildUrl(): You are using a ServerProxy but have not supplied it with a url.
I'm using a RestProxy, this is the store definition:
Ext.define('SF.store.Contents', {
requires: [
'SF.Config',
'SF.store.RestProxy'
],
extend: 'Ext.data.Store',
model: 'SF.model.Content',
autoLoad: false,
proxy: Ext.create('SF.store.RestProxy', {
url: (new SF.Config()).getApiBaseUrl() + "admin/contents"
}),
});
column code on GridPanel definition
....
store: 'Contents',
.....
{ xtype: 'actioncolumn', header: 'Action'
, width: 40
, items: [{ // Delete button
icon: '......./cancel.png'
, handler: function(grid, rowIndex, colindex) {
var record = grid.getStore().getAt(rowIndex);
record.set('status',6);
record.save(); //THIS CALL THROWS THE ERROR
grid.store.remove(record);
}
},......
In addition, the proxy is working fine for GET request. Does anyone knows what should I define on the proxy?
I've read the official doc but it is not clear for me.
You have to provide a proxy for you model. In the buttonĀ“s handler you are calling the model's save method (SF.model.Content) then, your SF.model.Content model has to provide a proxy.

Categories

Resources