I have a simple grid with the following code (along with the code of store and model).
var containerDetailsGrid = Ext.create('Ext.grid.Panel', {
store: storeVarContainerDetails,
tbar:[
{
xtype:'tbtext',
text:'Container Details'
}
],
columns: [
{
header : 'Ctr Size',
flex : 1,
dataIndex: 'ctrSize',
autoExpand:true,
align:'center'
}
],
height: 100
});
var storeVarContainerDetails = Ext.create('Ext.data.Store', {
model: 'VoyageMonitoringContainerDetailsModel',
proxy: {
type: 'ajax',
url: 'http://localhost/pnc/stores.php',
extraParams:{
action:'containerDetails'
},
reader: {
type: 'json'
}
},
autoLoad:true
});
Ext.regModel('VoyageMonitoringContainerDetailsModel', {
extend: 'Ext.data.Model',
fields: [
{type: 'string', name: 'ctrSize'}
]
});
The store is getting loaded and fetching the data but this data is just not getting displayed or actually is being visible in the grid.
When I inspect the grid element in DOM, then I can see the data to be there in 'td' of grid table, but that data is just not getting displayed.
There are other grids too on the page but all are displaying the data except this one. Also, there is no error being throw in console too.
Could anyone please throw some light at this that why it could be happening? Attached is a screen shot for more clarity.
PS: I am using ExtJS 4.
Posting the solution as an answer here so that it can help someone looking for the same and also I can mark this question as answered. The solution is - a grid should not be made the child of a container in a form, rather should be the child of fieldset in the form. I don't know the reason behind this, but works well for me. Hope this helps someone else too.
Did you try this on your store ?
autoLoad :true
Related
I'm trying to render a form within a custom row grid without success.
handler: function (button, record, pressed, eOpts) {
var grid = this.up('grid');
var store = grid.getStore();
var innerPanel = Ext.widget('form', {
//renderTo: record,
title: 'Title Test',
name: 'test',
items: [{
xtype: "textfield",
name: "testfield",
fieldLabel: "FooTest"
}]
});
// store.add(record);
store.add(innerPanel);
}
Any idea how to do this?
Fiddle: https://fiddle.sencha.com/#fiddle/183e
Thanks.
EDITED with taubi19 sugestion.
I think you don't quite understand the concepts yet. The form is a part of the view, the store is an object, that takes care of the data. You want to have a column in which each row is a form. This means you need a column whose xtype is not textfield, but something custom. I found out on senchas kitchen sink, that we need a 'widgetcolumn ' . In your fiddle, change the columns array with the following code and you will have a form in each new row.
columns:[
{
header:'Name',
dataIndex:'name',
flex:1,
xtype:'widgetcolumn',
widget:{
width:400,
xtype:'form',
items:[
{
xtype:"textfield",
name:"testfield",
fieldLabel:"FooTest"
},
{
xtype:"textfield",
name:"testfield1",
fieldLabel:"FooTest1"
}
]
}
}
]
And I suggest you remove adding the form to the store. You add records/data to stores. The store.add method takes a model instance as a parameter (Ext.data.Store.add).
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.
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!
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
});
I'm trying to learn how to use the EXTJS grids for some simple CRUD operations over a table in a admin app.
I have a simple grid that allows someone to edit users, the store is defined as:
var userDataStore = new Ext.data.Store({
id: 'userDataStore',
autoSave: false,
batch: true,
proxy: new Ext.data.HttpProxy({
api: {
read: '/Admin/Users/All',
create: '/Admin/Users/Save',
update: '/Admin/Users/Save'
}
}),
reader: new Ext.data.JsonReader(
{
root: 'Data',
idProperty: 'ID',
totalProperty: 'total',
successProperty: 'success',
messageProperty: 'message'
}, [
{ name: 'ID', type: 'string', allowBlanks: false },
{ name: 'NT_ID', type: 'string', allowBlank: false },
{ name: 'EMail', type: 'string', allowBlank: false },
{ name: 'Name', type: 'string', allowBlank: false },
{ name: 'Enabled', type: 'bool', allowBlank: false },
{ name: 'CurrentRoleCode', type: 'string', allowBlank: false}]
),
writer: new Ext.data.JsonWriter(
{
encode: false,
writeAllFields: true,
listful: true
})
});
This is bound to a grid, and I am able to load and save users without issue. The save button looks like this:
var saveButton = new Ext.Button({
text: 'Save',
disabled: true,
handler: function() {
userDataStore.save();
pageState.ClearDirty();
saveButton.disable();
}
});
However, when creating a new user, the JSON POST for the user is posted to the same REST service end point as "Update", with the only difference being that no ID value is posted (as one is only set in the store when loading from the server).
This works, and I am able to create users.
The save REST service emits back the created row with the new database ID, and I was under the assumption that EXTJS would automatically bind the new generated database ID to the row. This allows the user to further edit that row, and cause an update instead of a insert.
Instead, the row continues to have a blank user ID, so an additional save creates another new user.
So either:
EXTJS is supposed to resolve generated row ID's automatically and I am just doing something wrong.
I am supposed to manually reload the grid after each save with an additional REST call.
I've been looking at EXTJS documentation and forums, but I am unclear on the proper approach.
Can someone clarify?
EDIT: I tried returning Success = True in JSON to match the SuccessProperty, however this still didn't seem to work.
EDIT #2: So far the only thing I've found that works is doing "userDataStore.reload()" after saving, however because I was returning the contents of the store back after saving, I was hoping that EXTJS would understand that and update the row values.
I've got an idea that may help you. Let't suppose that user added a new
record in grid, in that moment add a new property newRecOrderNo to the record to
identify the record after response. When user will post data to server after
inserting you must get a new ID and associate it to newRecOrderNo
(like Map<Integer,Integer>). Then return json object like that :
{
success : true,
newIdes : {
1 : 23,
2 : 34
}
}
Then when you get response do set proper IDs to records:
userDataStore.each(function(rec){
if(rec.data.newRecOrderNo){
rec.data.ID = response.newIdes[rec.data.newRecOrderNo];
delete rec.data.newRedOrderNo;
}
})
})
Yes, it sets id (and also other fields, if server returns modified values of them), if create ajax backend returns record with set id, at least in extjs 4.1. You should return inserted record, with id set, under 'root' key as json dictionary, in this example root is 'Data', i.e.:
{
"Data": {
"ID": 8932,
"NT_ID": 28738273,
...
"CurrentRoleCode": "aaa",
},
"success": true
}
You need reload store with new params in savebtn handler
like
store.reload();
of course you can add more params to load action