I'm a first time user of jqGrid, so far I went trough official examples, I'm interested in loading data into grid either using json.
I'm currently looking at, Loading data(JSON Data):
http://trirand.com/blog/jqgrid/jqgrid.html
Here is a bit of javascript that creates grid :
jQuery("#list2").jqGrid(
{
url : '<c:url value="${webappRoot}/getdetails" />',
datatype : "json",
colNames : [ 'id', 'Location', 'Country Code', 'Type', 'Interval',
'Version', 'Last Active', 'Last Login', 'NOTE' ],
colModel : [
{ name : 'id', width : 10 },
{ name : 'location', width : 75 },
{ name : 'countryCode', width : 50 },
{ name : 'type', width : 40 },
{ name : 'interval', width : 30 },
{ name : 'version', width : 45 },
{ name : 'lastactive', width : 50, align : "right" },
{ name : 'lastlogin', width : 50, sortable : false },
{ name : 'note', width : 50, sortable : false}
],
rowNum : 10,
rowList : [ 10, 20, 30 ],
pager : '#pager2',
width: gridWidth,
sortname : 'id',
viewrecords : true,
sortorder : "desc",
caption : "JSON Example"
});
jQuery("#list2").jqGrid('navGrid', '#pager2',
{ edit : false, add : false, del : false});
${webappRoot}/getdetails transforms path to my project like http://localhost/myProject/getdetails, I'm using spring MVC(it might be irrelevant).
When I look in firebug this generates this http request :
GET http://localhost/newProject/getdetails?_search=false&nd=1304638787511&rows=10&page=1&sidx=id&sord=desc
200 OK
135ms
Here is the response :
{
"id": 1,
"location": "office_2782",
"countryCode": "UK",
"quarter": "500",
"version": "v3.05",
"lastactive": "yesterday",
"lastlogin": "today",
"note": "no note",
"type": "read-only"
}
When I navigate to JSON tab it all seems same as this, any idea what I'm doing wrong?
I'm trying to load only one record for start, and I can't get it working, any help is appriciated.
First of all you are not the first person who has problems understanding how the JSON data should be constructed, what the parameters sent from jqGrid to the server mean and so on. The official jqGrid documentation doesn't contain enough introduction, so the first steps of the jqGrid usage can be a little more difficult than one expect.
The problem which exists in your JSON response from the server is that it contains only one item of data instead of an array (or list) of items representing the grid rows. The data should be at least
[
{
"id": 1,
"location": "office_2782",
"countryCode": "UK",
"quarter": "500",
"version": "v3.05",
"lastactive": "yesterday",
"lastlogin": "today",
"note": "no note",
"type": "read-only"
}
]
or better as
{
"total": 1,
"page": 1,
"records": 1,
"rows": [
{
"id": 1,
"location": "office_2782",
"countryCode": "UK",
"quarter": 500,
"version": "v3.05",
"lastactive": "yesterday",
"lastlogin": "today",
"note": "no note",
"type": "read-only"
}
]
}
or even as
{
"total": 1,
"page": 1,
"records": 1,
"rows": [
{
"id": 1,
"row": [ "1", "office_2782", "UK", "500", "v3.05",
"yesterday", "today", "no note", "read-only" ]
}
]
}
or
{
"total": 1,
"page": 1,
"records": 1,
"rows": [
[ "1", "office_2782", "UK", "500", "v3.05", "yesterday", "today",
"no note", "read-only" ]
]
}
The reason of such strange at the first glance JSON data is that jqGrid is designed to support paging, sorting and filtering/searching of data implemented on the server. So the parameters rows=10&page=1&sidx=id&sord=desc from the url sent to the server mean that jqGrid asks the server to get the first page (page=1) of the data with the page having 10 rows per page (rows=10). The data should be previously sorted by id (sidx=id) in the descending order (sord=desc). If you has small number of rows (under some hundert for example) you can use client based sorting, paging and filtering if you add loadonce:true parameter of the jqGrid, but the server based implementation allows you to work with really large dataset having many hundred thousands rows of data with very good performace.
I recommend you to read my this answer where I tried to explain how the additional elements of the server response "total", "page" and "records" will be used. The values of the parameters can be encoded in JSON either as numbers or as strings (on your taste).
If the user clicks on the column header of the 'location' column for example jqGrid will send new request to the server having sidx=location&sord=asc in the url. So it is important to understand, that the server can be asked to provide the data for the grid not once per grid, but many times and the request will contain some parameters chosen by the user who works with the jqGrid.
Defining of jsonReader (and sometimes additional jsonmap parameters for every column) you describe the structure of the server response. Using the information jqGrid read the response and fill the grid.
The demo shows that with the corresponding jsonReader you can read even your original JSON data.
The last advice for you from me would be to consider at the beginning to use loadError event handle which helps to inform the user about the errors reported by the server. In the answer I have shown how it can be implemented in the case of ASP.NET MVC. I don't use spring MVC myself so I can't give you direct examples of how to better implement the error reporting in spring MVC, but the main idea is the same in any server technology: in case of errors the server should respond with the response having an error HTTP status code. Inside of your implementation of the loadError event handle you decode the response and display the information about the error.
Related
I am using Material UI DataGrid component to render EXCEL file. Each Excel file has several column Names and have specific types. For example:
const columns = [
{
"field": "uwgroup",
"headerName": "Group",
"minWidth": 200,
"editable": true
},
{
"field": "Amazing column Name ",
"flex": 1,
"minWidth": 150,
"editable": true
},
{
"field": "Building TSI",
"type": 'number',
"flex": 1,
"minWidth": 150,
"editable": true
},
{
"field": "dev",
"flex": 1,
"minWidth": 150,
"editable": true
}
]
The column Name Building TSI is of type number. And I am adding class name invalid using cellClassName, something like:
classnames({
invalid: !isPositiveNumber(params.value)
})
It works fine and renders class name and indicates error cells. The problem is, I want to count total number of error cells. The reason is, we only allow to save the grid values to the database, if there are no errors in any cells.
Solutions, I have tried so far:
Add state for errorCount and increment errorCount when I add class. This causes several re-renders and exceeds memory limit.
I tried to use document.getElementByClassNames('invalid') and check its length. It works only for the rendered item. That is to say, if excel file has more than 10 rows, it is paginated. The invalid cells count is only done for the currently rendered page.
I tried to use preProcessEditCellProps props to indicate error. However, I could not find anyway to get the total error cells count. Only thing, I could get out of this props is an ability to not allow user to enter incorrect value.
I even tried using localStorage. It has the exact same issue as solution number 2.
I would appreciate if anyone has faced similar scenario. It would be nice to get overall error cells count, so, I can enable to disable SAVE button.
One of the constraints that I have is the excel files are huge and contains on average of 30-40k rows and 25-40 columns. Adding state for each cells becomes less performant.
Thanks in advance!
Having another property in columns and referring to it before exporting for each cell/row can help.
In this example, invoke eligibleForExport function with the columns definiton and the actual data as parameters will give a boolean stating if error exists or not. Can be changed to count errors as well.
const isInvalidBuildingTSI=(value)=>!isPositiveNumber(value);
const isPositiveNumber=(num)=>num>=0;
const eligibleForExport=(columns,data)=>{
return !(data.find(row=>columns.find(column=>row[column.field]
&& typeof column["isValid"] === "function" && column["isValid"](row[column.field]))))
}
const columns = [
{
"field": "uwgroup",
"headerName": "Group",
"minWidth": 200,
"editable": true
},
{
"field": "Building TSI",
"type": 'number',
"flex": 1,
"minWidth": 150,
"editable": true,
"isValid" : isInvalidBuildingTSI,
"cellClassName":isInvalidBuildingTSI(param.value)?"invalid":""
}
];
If the initial data is always valid an easy way to solve your issue would be to follow the DataGrid documentation about clients side validation:
Client-side validation 🔗
To validate the value in the cells, first add a
preProcessEditCellProps callback to the column definition of
the field to validate. Once it is called, validate the value provided
in params.props.value. Then, return a new object contaning
params.props and also the error attribute set to true or false. If
the error attribute is true, the value will never be committed.
const columns: GridColDef[] = [
{
field: 'firstName',
preProcessEditCellProps: (params: GridEditCellPropsChangeParams) => {
const hasError = params.props.value.length < 3;
return { ...params.props, error: hasError };
},
},
];
For your scenario this would result in the following:
const columns = [
{
"field": "uwgroup",
"headerName": "Group",
"minWidth": 200,
"editable": true
},
{
"field": "Amazing column Name ",
"flex": 1,
"minWidth": 150,
"editable": true
},
{
"field": "Building TSI",
"type": 'number',
"flex": 1,
"minWidth": 150,
"editable": true,
preProcessEditCellProps(params) {
const invalid = !isPositiveNumber(params.props.value);
return { ...params.props, error: invalid };
}
},
{
"field": "dev",
"flex": 1,
"minWidth": 150,
"editable": true
}
]
There is an important difference with what you currently have. This validation only effects edits. So the initial data has to be valid. The advantage is that you no longer have to use classnames({ invalid: !isPositiveNumber(params.value) }) and the save button can always be enabled, since all committed changes can be assumed to be valid.
If the initial data can be invalid, this is probably not the answer you're looking for.
I am working on a project using Laravel and yajrabix/laravel-datatables. I am having an issue when trying to access a column using columndefs. The column is supposed to be JSON data. Nothing is working to work with the data in that column. Is there a way to send the data unmodified for that column?
Bottom line, I would like to be able to access the data from the json stored in the results column. No matter what I do, it doesnt work.
Here is the code in my blade view. Everything else works on the datatable.
<script type="text/javascript">
$(function () {
var table = $('.table').DataTable({
processing: true,
serverSide: false,
ajax: "/admin/logs/datatable/lookup-ip",
columns: [
{data: 'id', name: 'id'},
{data: 'ip_address', name: 'ip_address'},
{data: 'results', name: 'results'},
{data: 'created_by', name: 'created_by'},
{data: 'created_at', name: 'created_at'},
],
columnDefs: [
{
targets: "_all",
className: 'nk-tb-col tb-col-mb'
},
{
targets: 2,
render: function (data, type, row, meta) {
return 'ISP: ' + data.ip;
}
}
],
});
});
</script>
This is the function in the controller serving the datatable.
public function datatable($log)
{
switch($log)
{
case 'activity':
$table = config('activitylog.table_name');
break;
case 'lookup-ip':
$table = IPLookup::getModel()->getTable();
break;
case 'lookup-phone':
$table = PhoneLookup::getModel()->getTable();
break;
}
$query = DB::table($table);
return DataTables::of($query)->toJson();
}
This is the data that is stored in the database.
{"ip": "8.8.8.8", "asn": "AS15169", "isp": "Google LLC", "org": "Google LLC", "city": "Ashburn", "type": "IPv4", "region": "Virginia", "country": "United States", "success": true, "currency": "US Dollar", "latitude": "39.0437567", "timezone": "America/New_York", "continent": "North America", "longitude": "-77.4874416", "country_code": "US", "country_flag": "https://cdn.ipwhois.io/flags/us.svg", "timezone_gmt": "GMT -5:00", "country_phone": "+1", "currency_code": "USD", "timezone_name": "Eastern Standard Time", "continent_code": "NA", "currency_rates": "1", "country_capital": "Washington", "currency_plural": "US dollars", "currency_symbol": "$", "completed_requests": 29, "country_neighbours": "CA,MX,CU", "timezone_dstOffset": "0", "timezone_gmtOffset": "-18000"}
The model of the IP log has casts setup.
protected $casts = [
'results' => 'array',
];
Okay so it figures after posting the question... I figure it out.
According to yajrabox:
By default, Laravel DataTables protects us from XSS attack by escaping all our outputs. In cases where you want to render an html content, please use rawColumns api.
So I modified the code in the controller returning the datatable and now it works as expected and I can parse the JSON and use it as an object in javascript.
return DataTables::of($query)
->rawColumns(['results'])
->toJson();
One thing I've notice is that the data stored on your database, according to your example, isn't wrapped into the array brackets ([ ]) and you're using a cast on the Module. That could be the cause of the problem.
Try going to your database and manually wrapping your JSON on array brackets and give it a shot!
Hello I have made a web store using the Wix platform and I am having an issue connecting my custom coded table to a product page. The way I have it is the customer can search the products by title and the results populate a table with custom fields. The issue I am having is I want the customer to be able to click on a row and that will navigate them to the product page displaying the product they have clicked. here is my table in JSON object form which I got from the API docs and replace my own properties (works fine):
$w('#table1').columns = [{
"id": "col1", // ID of the column for code purposes
// The field key in the collection whose data this column displays
"dataPath": "mainMedia",
"label": "Image", // The column header
"width": 100, // Column width
"visible": true, // Column visibility
"type": "image", // Data type for the column
// Path for the column if it contains a link
"linkPath": "link-path-or-property" //<this is what the doc says
},
{
"id": "col2",
"dataPath": "name",
"label": "Name",
"width": 350,
"visible": true,
"type": "text",
"linkPath": "this is where I should have a link I think but what link"
}, {
"id": "col3",
"dataPath": "formattedPrice",
"label": "Price",
"width": 100,
"visible": true,
"type": "text",
"linkPath": "ProductPageUrl"
}, {
"id": "col4",
"dataPath": "sku",
"label": "SKU",
"width": 100,
"visible": true,
"type": "text",
} //,
// more column objects here if necessary
// ...
// ...
];
Then I use the built in function for my click event:
export function table1_rowSelect(event, $w) {
//Add your code for this event here:
console.log(event.rowData); //It does read the correct item clicked
}
Is this even possible?
You're in the right direction. Yes, linkPath is where you put the link to the product page. (You could also use the rowSelect event with wixWindow.to(), but you don't need to do both.) Now all you need to do is figure out the correct path to use in linkPath.
Looks to me like you're using a Wix Stores collection for your row data. If so, when setting the table columns, you use the field key (not field name) of the field that contains the link. So for the product page, use productPageUrl. Note, that this is per column. So if you want each cell to be a link, you have to add the linkPath to every column.
I am a beginner in TYPO3 and have to say its very complex but I am struggling my way through.
I just want a simple way to get content from an internal TYPO3 Database Table which I created and forward it to JavaScript/JQuery/AJAX.
My BootstrapTable is working but just displays static content from var data.
I know there are ways from pageType, eID and $GLOBALS['TYPO3_DB']->exec_SELECTgetRows( /* ... */ ); to get the content of the Database Table, but how to forward it to JavaScript and display it?
There should not be another database call with credentials, just a way to the internal Database.
Searching for this answer since 2 days but can't find any easy and plausible answer.
Or do I have to take the long road via eID or pageType?
Edit due to comment:
Here is my JavaScript with bootstrapTable:
$(function () {
$('#table').bootstrapTable({
idField: 'name',
pagination: true,
search: true,
data: data,
columns: [{
field: 'name',
title: 'Name'
}, {
field: 'stargazers_count',
title: 'Stars'
}, {
field: 'forks_count',
title: 'Forks'
}, {
field: 'description',
title: 'Description'
}],
onPostBody: function () {
$('#table').editableTableWidget({editor: $('<textarea>')});
}
});
});
var data = [{
"name": "bootstrap-table",
"stargazers_count": "526",
"forks_count": "122",
"description": "An extended Bootstrap table with radio, checkbox, sort, pagination, and other added features. (supports twitter bootstrap v2 and v3) "
}, {
"name": "multiple-select",
"stargazers_count": "288",
"forks_count": "150",
"description": "A jQuery plugin to select multiple elements with checkboxes :)"
}, {
"name": "bootstrap-show-password",
"stargazers_count": "32",
"forks_count": "11",
"description": "Show/hide password plugin for twitter bootstrap."
}, {
"name": "blog",
"stargazers_count": "13",
"forks_count": "4",
"description": "my blog"
}, {
"name": "scutech-redmine",
"stargazers_count": "6",
"forks_count": "3",
"description": "Redmine notification tools for chrome extension."
}
];
And calling it in my html with : <table id="table"></table>
My own created table in mysql database is: tx_table
I want the content of that table to be displayed in my bootstraptable Table
First solution. You can output your results directly into html using <script> tag and v:format.json.encode ViewHelper
action code:
$yourDataArrayFromPHP = array(
'var1' => 'val1',
'var2' => 'val2'
);
$this->view->assign('yourDataArrayFromPHP', $yourDataArrayFromPHP);
html:
<script>
var data = {v:format.json.encode(value: '{yourDataArrayFromPHP}')}
</script>
Now you can access this data in javascript data.var1
Also keep in mind that your data should be before bootstrapTable initialization.
I'm working on an application that lets our security dispatchers update a page that contains current road and campus conditions. The backend is a nodejs/express stack with and the data is a simple JSON structure that looks something like this:
{
"campus": {"condition": "open", "status": "normal"},
"roads": {"condition": "wet", "status": "alert"},
"adjacentroads": {"condition": "not applicable", "status": "warning"},
"transit": {"condition": "on schedule", "status": "normal"},
"classes": {"condition": "on schedule", "status": "normal"},
"exams": {"condition": "on schedule", "status": "normal"},
"announcements" : "The campus is currently under attack by a herd of wild velociraptors. It is recommended that you do not come to campus at this time. Busses are delayed.",
"sidebar": [
"<p>Constant traffic updates can be heard on radio station AM1234. Traffic updates also run every 10 minutes on AM5678 and AM901.</p>",
"<p>This report is also available at <strong>555-555-1234</strong> and will be updated whenever conditions change.</p>"
],
"links": [
{
"category": "Transportation Links",
"links": [
{
"url": "http://www.localtransit.whatever",
"text" : "Local Transit Agency"
},
{
"url": "http://m.localtransit.whatever",
"text" : "Local Transit Agency Mobile Site"
}
]
},
{
"category": "Weather Forecasts",
"links": [
{
"url": "http://weatheroffice.ec.gc.ca/canada_e.",
"text" : "Environment Canada"
},
{
"url": "http://www.theweathernetwork.com",
"text" : "The Weather Network"
}
]
},
{
"category": "Campus Notices & Conditions",
"links": [
{
"url": "http://www.foo.bar/security",
"text" : "Security Alerts & Traffic Notices"
},
{
"url": "http://foo.bar/athletics/whatever",
"text" : "Recreation & Athletics Conditions"
}
]
},
{
"category": "Wildlife Links",
"links": [
{
"url": "http://velociraptors.info",
"text" : "Velociraptor Encounters"
}
]
}
],
"lastupdated": 1333151930179
}
I'm wondering what the best way of working with this data on the client side would be (e.g. on the page that the dispatchers use to update the data). The page is a mix of selects (the campus, roads, etc conditions), TinyMCE textareas (announcements and sidebar) and text inputs (links). I'm open to changing this data structure if necessary but it seems to me to work well. I've been looking at Backbone, and also Can.JS but I'm not sure if either of those are suitable for this.
Some additional information:
there's no need to update an individual item in the data structure separatly; I plan on POSTing the entire structure when it's saved. That said...
there's actually two different views, one for the dispatchers and another for their supervisors. The dispatchers only have the ability to change the campus, roads, etc conditions through drop-downs and furthermore can only change the "condition" key; each possible condition has a default status assigned to it. Supervisors can override the default status, and have access to the announcements, sidebar and links keys. Maybe I do need to rethink the previous point about POSTing the whole thing at once?
the supervisors need to be able to add and remove links, as well as add and remove entire link categories. This means that DOM elements need to be added and removed, which is why I'm thinking of using something like Backbone or Can.js instead of just writing some ghetto solution that looks at all the form elements and builds the appropriate JSON to POST to the server.
Suggestions welcomed!
CanJS works great with nested data. can.Model is inheriting can.Observe which allows you to listen to any changes in the object structure.
If you include can.Observe.Delegate you have even more powerful event mechanism (example from the docs):
// create an observable
var observe = new can.Observe({
name : {
first : "Justin Meyer"
}
})
var handler;
//listen to changes on a property
observe.delegate("name.first","set",
handler = function(ev, newVal, oldVal, prop){
this //-> "Justin"
ev.currentTarget //-> observe
newVal //-> "Justin Meyer"
oldVal //-> "Justin"
prop //-> "name.first"
});
// change the property
observe.attr('name.first',"Justin")