I have a PHP script that extract valid GeoJSON data from a database. Now I would like to prepare a grid view of these data with jqgrid, but I can't figure out the proper jsonReader for the javascript code.
This is my GeoJSON output:
{"type":"FeatureCollection",
"total":0,
"page":1,
"records":117,
"features":[
{"geometry":{"type":"Point","coordinates":[12.3,41.70052]},
"type":"Feature",
"properties":{
"data":"2006-02-22",
"specie":"S. coeruleoalba",
"localita":"Ostia",
"provincia":"Roma"
},"id":0},
{"geometry":{
"type":"Point","coordinates":[15.26667,40.0502]},
"type":"Feature",
"properties":{
"data":"2006-03-01",
"specie":"S. coeruleoalba",
"localita":"Golfo di Salerno",
"provincia":"Salerno"
},"id":1},
{"geometry":{"type":"Point","coordinates":[14.88333,40.56692]},
"type":"Feature",
"properties":{
"data":"2006-03-03",
"specie":"S. coeruleoalba",
"localita":"Battipaglia",
"provincia":"Salerno"
},"id":2}
]}
Using this reader my grid shows the right number of rows (117) and pages, but empty cells
jsonReader : {
root: "features",
page: "page",
total: "total",
records: "records",
repeatitems: false,
cell: "properties",
id: "id"
}
Can someone help me to write a working reader? Thanks in advance
Your main error is that you try to use cell: "properties", but cell property will be ignored in case of usage of repeatitems: false property.
You should just use
jsonReader: {
root: "features",
repeatitems: false
}
and then define jsonmap property for every column. For example you can use the following column definition:
colModel: [
{name: 'coordX', jsonmap:'geometry.coordinates.0', width: 75, sorttype: 'number',
formatter: 'number', formatoptions: {decimalPlaces: 5}},
{name: 'coordY', jsonmap:'geometry.coordinates.1', width: 75, sorttype: 'number',
formatter: 'number', formatoptions: {decimalPlaces: 5}},
{name: 'data', jsonmap:'properties.data', width: 90, align: 'center',
sorttype: 'date', datefmt: 'm/d/Y',
formatter: 'date', formatoptions: {newformat: 'm/d/Y'}},
{name: 'specie', jsonmap:'properties.specie', width: 100},
{name: 'localita', jsonmap:'properties.localita', width: 100},
{name: 'provincia', jsonmap:'properties.provincia', width: 80}
]
As the result you will be able to read your JSON data to the following grid:
(see the demo here). In your JSON data I changed only total value from 0 to 1 because it has no sense to have the total value less as the page value.
Related
I dont know how to tell but i still dont get it right. This is my code :
Ext.define("PL.view.list.listOnly", {
extend: 'Ext.form.Panel',
alias: 'widget.listlistonly',
config:{
fullscreen: true,
title: 'Master barang',
items:[{
xtype : 'panel',
layout: {
type: 'fit',
align : 'stretch',
pack : 'start',
},
defaults: {
allowBlank: true,
msgTarget: 'side',
labelWidth: 60,
margin: '5 5 5 5',
},
items:[{
xtype:'list',
height: '100%',
masked: { xtype: 'loadmask',message: 'Loading...' },
scrollable: {
direction: 'vertical',
directionLock: true
},
store:{
fields: [{
name:'szName',
},{
name:'szProductID',
},{
name:'szBarcode',
}],
autoLoad: true,
pageSize: 20,
proxy: {
type: 'ajax',
url: 'store/product/loadData.php',
pageParam: 'param',
reader: {
type: 'json',
rootProperty: 'topics',
}
}
},
variableHeights: false,
useComponents: true,
itemTpl: '<div class="myButton">' +
'<input type="button" name="{szProductID}" value="Edit" ' +
'style="padding:3px;">' +
'</div>' +
'<div class="myContent">'+
'<div>PLU : <b>{szProductID}</b>, Barcode: <b>{szBarcode}</b></b></div>' +
'<div>Nama: <b>{szName}</b></div>' +
'</div>',
}]
}],
scrollable : false,
},
});
And this is what i get from json :
{"topics": [{
"szProductID": 1001,
"szBarcode": 002,
"szName": "STANDARD BLACK"
},{
"szProductID": 1100420020479,
"szBarcode": 1100420020479,
"szName": "STANDARD BLUE"
}],
"totalCount": 2}
As you can see, there is a '002' (szBarcode field), and this is my problem. The list only show '2' instead of '002'. This should show '002' as szBarcode but i dont know how to fix this.
Any help would appreciate
The problem is that barcode: 002 and barcode: 2 mean exactly the same in JSON format. Prepended zeros for numbers just don't count.
There are about four different things you can possibly do.
If you can access the server code, you can change it to send you the barcode field as a string (barcode:"002").
If your barcode ALWAYS has a certain length (say 13), you can work with the number you have, and pad it to the required length again. Please be aware that after a certain length, there are precision issues because numbers are stored in fixed-length memory, while a string's memory always is as long as needed. Sample conversion code:
name:'barcode',
convert:function(value) {
var str = value.toString(),
pad = "0000000000000"; // expand to length of your number
return pad.substring(0, pad.length - str.length) + str);
}
(Bonus: This code does not break when someone does (1) afterwards...)
If you have no other barcode fields in your JSON, you could use a regular expression to add the necessary quotes to the JSON client-side before deserialization.
You could override ExtJS's default JSON serialization/deserialization code. Please note that this is not as easy as it sounds and may have quite some side effects. This is the only suitable way if you want to send barcode as zero-padded JSON numbers back to the server as well.
I have a page containing a ExtJS 4.2.2 dataStore and gridPanel showing items created using information from various tables in a MySQL database.
The purpose of the generated grid is to provide a "confirmation" to the user before any information is actually generated in the database in a table separate to those that originated the initial information, as some items can be flagged to be imported; unflagged items are not imported. The page uses HTML, PHP (with CodeIgniter MVC framework) and ExtJS (which implies Javascript and JQuery).
With my current understanding of ExtJS, I would perform the necessary database insert or update by:
Saving all the changes in the grid to the store
Packaging the store's data into a multidimensional array, which is then assigned into a POST variable in some similar manner to a form
Perform a POST to the same page, picking up the POST variable
Loop through the POST information, passing each row's data to the model to perform the SQL query and INSERT/UPDATE as necessary.
I'm thinking this is a long-winded and most likely inefficient method for doing this; having previously worked with Kendo UI, I would have thought there is some form of "save" action on the store that simply calls a controller/model function that would act on the data in fewer steps.
Having looked at Ext.data.Store's numerous potential candidates (the commitChanges method, update event, the write event, store.sync etc.), I have to say I'm completely bewildered by how I could perform the kind of action I'm thinking of; I need to write the information to a table separate from those that generated the initial information, and none of the above seem to do that.
I would appreciate a "simple words" play-by-play of how to get the "dirty" data from the grid saved to the store, then the store data being passed to a MVC Controller-then-Model function that allows for update/insert to the DB (if that is the best way to do this) - I also appreciate that I will have to modify aspects of my ExtJS code, but what about my current setup isn't helping, if anything?
ExtJS code below renders the grid with data, and not much else:
Ext.Loader.setConfig({
enabled: true
});
Ext.Loader.setPath('Ext.ux', '../ux');
Ext.require([
'Ext.ux.CheckColumn'
]);
Ext.onReady(function(){
Ext.define('ConfirmationModel', {
extend: 'Ext.data.Model',
fields: [
'GroupName', // generated if not a member of a group, will eventually be retrieved if already existing in group by checking import table for JobNo, ItemNo and ItemTypeId
'ItemType',
'ItemTypeId',
'JobNo',
'ItemNo',
'ThicknessDepth',
'Cutter',
'CutterId',
'Source',
'Qty',
'Material',
'MaterialId',
'Type',
'TypeId',
'Work',
'WorkId',
'PaintInternal',
'PaintExternal',
'Notes',
'Documented',
'ImportDate', // fetched by checking import table for jobNo, itemNo and itemTypeId
'ImportCheck' // usually automatically checked if not yet imported
]
});
confirmationStore = Ext.create('Ext.data.Store',{
model: 'ConfirmationModel',
autoLoad: true,
proxy: {
// load using HTTP
type: 'ajax',
url: '<?= $site_url ?>Production/ConfirmationJSON/<?php echo $job_no ?>', // currently pulls all the information from three separate tables, pushes to object arrays then converts to and returns as JSON; will also check import table for existing entries as further work
pageParam: false, //to remove param "page"
startParam: false, //to remove param "start"
limitParam: false, //to remove param "limit"
noCache: false, //to remove param "_dc"
reader: {
type: 'json',
model: 'ConfirmationModel'
}
},
groupField: 'GroupName'
});
confirmationGrid = Ext.create('Ext.grid.Panel', {
width: 1200,
store: confirmationStore,
title: 'Import Confirmation',
tbar: [
{
xtype: 'button',
text: 'Update',
handler: function(){
// function to handle the save/update of information goes here?
document.location.href = '<?php echo site_url() ?>Production/Schedule'; // redirect to next page in steps
}
},
{
xtype: 'button',
text: 'Cancel',
handler: function(){
window.history.back();
}
}
],
columns: [
{ text: 'Item<br />No.', width:50, dataIndex: 'ItemNo' },
{ text: 'Job<br />No.', width: 65, dataIndex: 'JobNo' },
{ text: 'Item Type', width: 70, dataIndex: 'ItemType' },
{ text: 'Thickness<br />Depth', width: 65, dataIndex: 'ThicknessDepth' },
{ text: 'Cutter', width: 65, dataIndex: 'Cutter' },
{ text: 'Source', width: 65, dataIndex: 'Source' },
{ text: 'Qty', width: 40, dataIndex: 'Qty' },
{ text: 'Material', flex: 1, dataIndex: 'Material' },
{ text: 'Type', flex: 2, dataIndex: 'Type' },
{ text: 'Work', flex: 2, dataIndex: 'Work' },
{ text: 'Paint - Internal', flex: 2, dataIndex: 'PaintInternal' },
{ text: 'Paint - External', flex: 2, dataIndex: 'PaintExternal' },
{ text: 'Notes', flex: 2, dataIndex: 'Notes' },
{ text: 'Documented?', width: 75, dataIndex: 'Documented' },
{ text: 'Import<br />Date', width: 60, dataIndex: 'ImportDate' },
{
xtype: 'checkcolumn',
sortable: false,
header: 'Import?',
width: 50,
dataIndex:'ImportCheck'
}
],
features: [{
id: 'group',
ftype: 'groupingsummary',
groupHeaderTpl: '{name}',
enableGroupingMenu: false
}],
renderTo: Ext.get('sencha_confirmation')
});
});
There's no need to save data from the grid to the store, since the content you're seeing in the grid is there because it is already in the store (given that the store is the data provider for the grid).
To send the data in this format, you simply need to configure your proxy's writer's allowSingle: false. This will force the proxy to send through the records it is persisting as an array always, even if there is only one record.
Example:
proxy: {
writer: {
allowSingle: false
},
...
}
This can be accomplished by calling sync() on your store. Sync will automatically create a request to the url specified on your proxy, and will batch together new records, updated records, and deleted records. You can call this manually, or add autoSync: true to your store (I prefer controlling when it's called, but that's up to you).
Re: the MVC side of things, that's dependent on how your application is structured. For example, if you have a "save" button on the grid, you could bind to the button's click event, and in your controller listen for this click event and call your store's sync() method there. Of course, this is just an example: there are an number of events/conditions you could respond to and do the same thing.
I have looked here for similar queries, and none quite answer my question, either in its entirety, or in a fashion I can understand.
I retrieve a string value from a MySQL database representing a datetime, i.e. "03 Oct, 2013 05:30:45PM" is represented as "20131003173045" in the database. This value is presented in a "Last Login" column in a Kendo Grid as a date. This is all contained within a PHP-oriented webpage using the MVC framework.
Previously I applied a date format in the SQL query to change the string from "20131003173045" to "03 Oct, 2013 05:30:45PM", but this gets presented in the KendoGrid as a string, meaning November Dates can appear before October dates, April dates come up first etc. This understandably is not the desired function, especially when trying to sort by this column.
Sample Code for the page rendering the KendoGrid:
<div class="div1">
<div>
<table id="listGrid"></table>
</div>
</div>
<script>
$(function() {
$("#grid").kendoGrid({
scrollable: false,
groupable: false,
sortable: {
mode: "multiple"
},
resizable: true,
pageable: true,
dataSource:
{
transport:
{
read: {
url: "<?= $site_url ?>Settings/Users/List",
dataType: "json"
},
parameterMap: function (model, operation) {
if (operation == "read") {
return model;
}
else if(model) {
return { "json" : kendo.stringify(model) };
}
else
return "";
}
},
pageSize: 20,
serverPaging: true,
serverSorting: true,
sort: { field: "LastLogin", dir: "desc" },
serverGrouping: true,
serverAggregates: false,
schema: {
total: "total",
data: "data",
groups: "groups"
}
},
toolbar: [ { title: "", template:'<a class="k-button k-button-icontext k-grid-add" href="<?= $site_url ?>Settings/Users/Add/">Add New User</a>' }],
columns: [
//{field: "Id", width: "40px"},
{field: "UserName", title: "Alias", width: "160px"},
{field: "ForeName", title: "Forename", width: "100px"},
{field: "SurName", title: "Surname", width: "160px"},
{field: "Initials", width: "80px"},
{field: "CrmId", title: "CRM ID", width: "100px"},
{field: "Dept", title: "Department", width: "100px"},
{field: "Position"},
// Below is the field in question
{field: "LastLogin", title: "Last Login", width: "160px"},
{field: "BlockedStatus", title: "Status", width: "90px"},
{ title: "", template:'<a class="k-button k-button-icontext k-grid-edit" href="<?= $site_url ?>Settings/Users/Update/#: Id #">Edit</a>' }
]
});
});
</script>
I've looked at the kendo.parseDate and kendo.toString, and combining the two, but can't seem to get anything to work; I either get "null" or "20131003173045", or the page doesn't load.
I can't change the database data, I can only format it as part of the SQL query, which is what I was doing initially.
I need the whole "20131003173045" string to become "03 Oct, 2013 05:30:45PM", and still be ordered in proper chronological order - how can I do this, and if the kendo.parseDate and kendo.toString are the correct tools to use, what am I doing wrong?
What I suggest is implement a schema.parse function that converts that MySQL format to a Date object and then use columns.format for formatting it.
The Schema would be:
schema : {
data : "data",
total : "total",
groups: "groups",
parse : function (d) {
$.each(d.data, function (idx, elem) {
elem.LastLogin = kendo.parseDate(elem.LastLogin, "yyyyMMddHHmmss");
});
return d;
}
}
Now, the columns definition for printing the date would define a format that is the one that you want.
{field: "LastLogin", title: "Last Login", width: "160px", format: "{0:dd MMM, yyyy hh:mm:sstt}" }},
I have list of links in one page which is dynamically created. I want to do when I click on one link another page will be open and according to link id which is i am sending the data will be fetch from database and load into a pagination ext data grid.
Bellow in my Javascript code
var extGrid = null;
var center_data_store=null;
var exam_id = null;
Ext.onReady(function(){
// create the data store
exam_id = document.getElementById("hdnExamId").value;
//I am getting id from one hidden field.
//alert(exam_id);// Id is coming.
multiple_choice_all_data_store = new Ext.data.JsonStore({
totalProperty: 'total', // total data, see json output
root: 'results', // see json output
url: 'multiple_choice_all_data_grid.php"?exm_id="+exam_id',
//in above url I am passing data.
fields: [
{name: 'OEXM_Id', type: 'int'},
'OEXM_txtareaQuestion','OEXM_rbtnOption','OEXM_txtOption1','OEXM_txtOption2','OEXM_txtOption3','OEXM_txtOption4','OEXM_txtExamId','OEXM_txtExamName'
]
});
// load data from the url ( data.php )
multiple_choice_all_data_store.load({params:{start: 0, limit: 15}});
// create the Grid
var multiplechoicealldataGrid = new Ext.grid.GridPanel({
store: multiple_choice_all_data_store,
columns: [
new Ext.grid.RowNumberer(),
//{header: 'ID', width: 30, sortable: true, dataIndex: 'OEXM_Id',hidden:false},
{header: 'Question', width: 300, sortable: true, dataIndex: 'OEXM_txtareaQuestion',hidden:false},
{header: 'Answer', width: 100, sortable: true, dataIndex: 'OEXM_rbtnOption',hidden:false},
{header: 'Option1', width: 100, sortable: true, dataIndex: 'OEXM_txtOption1',hidden:false},
{header: 'Option2', width: 100, sortable: true, dataIndex: 'OEXM_txtOption2',hidden:false},
{header: 'Option3', width: 100, sortable: true, dataIndex: 'OEXM_txtOption3',hidden:false},
{header: 'Option4', width: 100, sortable: true, dataIndex: 'OEXM_txtOption4',hidden:false}
],
stripeRows: true,
height:470,
width:792,
title:'All Multiple Choice Question Information',
bbar: new Ext.PagingToolbar({
pageSize: 15,
store: multiple_choice_all_data_store,
displayInfo: true,
displayMsg: 'Displaying Records {0} - {1} of {2}',
emptyMsg: "No topics to display"
})
});
My problem is I am not able to get ID value in my PHP Page.
Try change url in the store definition to 'multiple_choice_all_data_grid.php?exm_id='+exam_id
Then your id should be available in PHP in $_GET['exm_id'] variable
To get a element in ExtJS:
exam_id = Ext.getCmp("hdnExamId").getValue();
The getValue() method is used to retrieve the value of the element.
Edit:
Also fix the url #Lolo is pointing out.
Hello StackOverFlow nation . I'm trying to add information to jqGrid , which is retrieved from MySQL database. I've two files => index.html and data.php (both in the same directory)
index.html source =>
<script type="text/javascript">
$(function(){
$("#jqGrid_tb").jqGrid({
url: "data.php",
datatype: "json",
sortable: true,
height: "auto",
colNames: ["Name","Surname","Birth Year","Famous Film"],
colModel: [
{name: "name", index: "name", width: "150"},
{name: "surname", index: "surname", width: "150"},
{name: "b_year", index: "year", width: "150"},
{name: "film", index: "film", width: "200"}
],
rowNum: 5,
rowList: [5,10,15],
viewrecords: true,
pager: $("#pager"),
caption: "Famous Actors",
}).navGrid("#pager");
});
</script>
<div id="grid">
<table id="jqGrid_tb"></table>
<div id="pager"></div>
</div>
data.php source =>
include ("JSON.php");
$json = new Services_JSON();
$con = new mysqli("host","user","pswd","db");
if (!$con->connect_errno){
if ($r = $con->query("SELECT * FROM actors")){
while ($row = $r->fetch_assoc()){
$info[] = array(
"name" => $row[name],
"surname" => $row[surname],
"b_year" => $row[b_year],
"film" => $row[film],
);
}
$r->free();
}
}
echo $json->encode($info);
if (isset($con)){
$con->close();
}
jqGrid is shown without any information in index.html file , also when opening data.php file information is successfully encoded into JSON format , whats wrong I can't understand . Please help , thanks ...
Your response format is wrong. You can go to jqGrid Demos page where you will find a sample for PHP/MySQL after expanding Loading Data and then choosing JSON Data.
The proper format of data should look like this:
{
"total": "1",
"page": "1",
"records": "2",
"rows": [
{ "name": "Robert", "surname": "De Niro", "b_year": "1943", "film": "Once Upon A Time In America" },
{ "name": "Al", "surname": "Pacino", "b_year":"1971", "film": "Scent Of A Woman"}
]
}
Where:
total --> total count of pages
page --> current page number
records --> total count of records
rows --> the rows of data
Also if you want rows to be objects, you need to disable repeatitems in jqGrid jsonReader options:
$("#jqGrid_tb").jqGrid({
...
jsonReader: { repeatitems: false }
});
It is also adviced for rows to have unique id for later reference.
You should include
jsonReader: {
repeatitems: false,
root: function (obj) { return obj; },
page: function (obj) { return 1; },
total: function (obj) { return 1; },
records: function (obj) { return obj.length; }
}
as additional option of jqGrid is you don't want to change format of input data. Moreover you should specify which values should assign jqGrid as id attribute of the row. You can include additional id property as additional property of every returned item or you can add key: true property to the column (in colModel) which contains unique values. For example if you can guarantied that the values from "name" are already unique then you can include key: true property in definition of "name" column.
Additionally you can consider to use loadonce: true option of jqGrid. In the case the full data of the grid will be loaded at once and the sorting, paging and searching (filtering) of data will be implemented by jqGrid on the client side without needs to implement some additional code on the server side. You should don't use the option in case of large number of rows (many hundred or many thousand rows) in the grid.