i am tried to delete data from my DB using the ext.js script below:
it seem to be working on the browser when i clicked on the icon "Delete" but when i clicked on some other toolbar tap some whereat the browser. it was reloaded with my same data on the row grid. I really don't know that i only delete only the Array but not delete the actual DB by sending wrong servers or methods. I don't know. I am tried using different method to delete it but it same problem came back.
Can anyone help me? I am new to ext.javascript or ext.Ajax ...etc..
codes:
var userHistoryGrid = Ext.create('Ext.grid.Panel', {
width: 880,
height: 450, //autoHeight: true, collapsible: false, title: 'Employee\'s Request History', icon: 'images/newtodo1.png', store: userHistoryStore, multiSelect: false, columnLines: false, enableColumnHide: false, enableColumnMove: false, enableColumnResize: false, selType: 'rowmodel',
viewConfig: {
emptyText: 'No prior requests',
stripeRows: false,
enableTextSelection: true,
getRowClass: function (record) {
return record.get('Status') == 'Approved' ? 'normal-row' : 'hilite-row';
}
},
items: [{
icon: 'images/delete.png',
tooltip: 'Delete Request',
handler: function (grid, rowIndex, colIndex) {
record = grid.getStore().getAt(rowIndex);
cellvalue = record.get('Delete');
if (cellvalue != 'Delete') {
Ext.MessageBox.confirm(
'Confirm Deletion',
'Delete this request?',
function (btn) {
if (btn == 'yes') {
cellvalue = record.get('EventID');
Ext.Ajax.request({
url: 'delUserHistoryGrid.asp',
async: false,
method: 'DELETE',
params: {
id: userHistoryStore
},
timeout: 30000,
success: function (result) {
userHistoryStore.reload();
userinfoStore.reload();
}
});
//delete userHistoryStore[rowIndex];
userHistoryStore.removeAt(rowIndex);
//eventStore.destroy(rowIndex);
//userHistoryStore.destroy(rowIndex);
//record.EventID.removeAt(grid);
userinfoStore.reload();
} else {
rowEditing.cancelEdit();
}
});
}
}
},
Some hints to help you pinpoint your issue:
Do not remove the record from the store after the ajax call. Only do it if it was succssful. Move userHistoryStore.removeAt(rowIndex); inside the success callback.
I don't think async: false actually exists. So your ajax call returns immediately. You should continue the flow of execution in the callback.
Add a failure callback and check (breakpoint or log) the reponse you get. You should also check the response in the success case as there might be some message of interest there too. Depends on the service.
Use your browsers dev tools and check the network. You should first verify that the ajax call is executed succesfully and then that you receive a valid reply. Check the response code. If it's not in the 200s it's an error. You can search the web more once you see the response code you get.
Without knowing anything about your services or your app I think passing the whole store as your id param is probably wrong. Shouldn't you pass the cellvalue?
Related
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.
I am filtering data from server side proxy :
id: 'projectStore',
model: 'project',
remoteSort: true,
remoteFilter: true,
autoLoad: true,
autoSync: true,
proxy: {
type: 'rest',
url: 'app/projects.php',
reader: {
type: 'json',
root: 'projects'
}
}
this is my filter code :
projectStore.clearFilter();
var comboArray = [
Ext.getCmp('projectCombo').getValue(),
Ext.getCmp('statusCombo').getValue(),
Ext.getCmp('typologyCombo').getValue(),
Ext.getCmp('donorCombo').getValue(),
Ext.getCmp('programCombo').getValue(),
Ext.getCmp('regionCombo').getRawValue(),
Ext.getCmp('cityCombo').getRawValue()
];
if (comboArray[0] != "All" && comboArray[0] != 'default combo value') {
projectStore.filter('PRJ_TYPE', comboArray[0]);
}
if (comboArray[1] != "All" && comboArray[1] != 'default combo value') {
projectStore.filter('PRJ_STATUS', comboArray[1]);
}
... And so on,
when I EXTJS sends request to server, server response is correct and grid is loading filtered data for about 2-3 seconds then it becomes unfiltered again! I need it to be filtered until I will clear filter myself, I have tried many things but couldn't find solution for that. thank you in advance!
These are the symptoms of a race condition.
Since your store is configured as autoLoad, it gets loaded unfilteted when the store is instantiated. Then immediately you filter it. If the store's unfiltered load takes a few seconds longer than the filtered load, you will get what you describe.
The solution is to set autoLoad to false and to load the store manually ( if it doesn't already load automatically when you apply the filter ).
Can't we make synchronous calls with Ext.data.Store?
I have a model which I'm loading inside a store. Later I'm binding it to a combobox. This flow works fine.
But when I want to set value of combo for default selection, I get JS error saying no elements inside the store. The reason being, the ajax call to fill the store is made after all the JS is executed. I tried making async property to false, but still no luck!!!
Here is my code snippet:
var store = new Ext.data.Store({
proxy: {
type: 'ajax',
url: '/GetAccounts',
reader: {
type: 'json'
}
},
async: false, //Tried this...no luck
cache: false,
autoLoad: true
});
var simpleCombo = Ext.create('Ext.form.field.ComboBox', {
fieldLabel: 'For ',
renderTo: 'simpleCombo',
displayField: AccountName,
valueField: 'AccountId',
store: store,
queryMode: 'local',
forceSelection: true
});
simpleCombo.setValue(store.getAt(0).get('AccountId')); //JS ERROR AT THIS LINE. No elements in the store
Disable the combo until the store is populated. Don't mess with sync request you will freeze the whole page (or even the browser) until the requests finishes.
I posted something similar at https://stackoverflow.com/a/12918140/1449525, but I took this kind of approach:
Add listeners to your combo box so that when the combo box is actually rendered, it should try to set its value
listeners:{
scope: this,
afterRender: this.selectFirstComboItem
}
then add the method to your this (or wherever you prefer).
selectFirstComboItem: function(combo) {
// This will tell us if the combo box has loaded at least once
if (typeof combo.getStore().lastOptions !== "undefined") {
// Grab the first value from the store
combo.setValue(combo.getStore().first().get(combo.valueField));
}
else {
// When the store loads
combo.getStore().on("load", function(store, items){
// Grab the first item of the newly loaded data
combo.setValue(items[0].get(combo.valueField));
});
}
}
I created a Grid component with the store configuration like this:
//Create the store
config.store = new Ext.data.Store({
restful: true,
autoSave: false,
batch: true,
writer: new Ext.data.JsonWriter({
encode: false
}),
reader: new Ext.data.JsonReader({
totalProperty: 'total',
root: 'data',
fields: cfg.fields
}),
proxy: new Ext.data.HttpProxy({
url:cfg.rest,
listeners:{
exception: {
fn: function(proxy, type, action, options, response, arg) {
this.fireEvent('exception', proxy, type, action, options, response, arg);
},
scope: this
}
}
}),
remoteSort: true,
successProperty: 'success',
baseParams: {
start: 0,
limit: cfg.pageSize || 15
},
autoLoad: true,
listeners: {
load: {
fn: function() {
this.el.unmask();
},
scope: this
},
beforeload: {
fn: function() {
this.el.mask("Working");
},
scope: this
},
save: {
fn: function(store, batch, data) {
this.el.unmask();
this.fireEvent('save', store, batch, data);
},
scope: this
},
beforewrite: {
fn: function(){
this.el.mask("Working...");
},
scope: this
}
}
});
Note: Ignore the fireEvents. This store is being configured in a shared custom Grid Component.
However, I have one problem here: Whatever CRUD actions I did, I always come out with N requests to the server which is equal to N rows I selected. i.e., if I select 10 rows and hit Delete, 10 DELETE requests will be made to the server.
For example, this is how I delete records:
/**
* Call this to delete selected items. No confirmation needed
*/
_deleteSelectedItems: function() {
var selections = this.getSelectionModel().getSelections();
if (selections.length > 0) {
this.store.remove(selections);
}
this.store.save();
this.store.reload();
},
Note: The scope of "this" is a Grid Component.
So, is it suppose to be like that? Or my configuration problem?
I'm using Extjs 3.3.1, and according to the documentation of batch under Ext.data.Store,
If Store is RESTful, the DataProxy is also RESTful, and a unique transaction is generated for each record.
I wish this is my configuration problem.
Note: I tried with listful, encode, writeAllFields, encodeDelete in Ext.data.JsonWriter... with no hope
Just for those who might wonder why it's not batch:
As for the documentation stated,
If Store is RESTful, the DataProxy is also RESTful, and a unique transaction is generated for each record.
Which is true if you look into the source code of Ext.data.Store in /src/data/Store.js
Line 309, in #constructor
// If Store is RESTful, so too is the DataProxy
if (this.restful === true && this.proxy) {
// When operating RESTfully, a unique transaction is generated for each record.
// TODO might want to allow implemention of faux REST where batch is possible using RESTful routes only.
this.batch = false;
Ext.data.Api.restify(this.proxy);
}
And so this is why I realize when I use restful, my batch will never get changed to true.
You read the docs correctly; it is supposed to work that way. It's something to consider whenever choosing whether to use RESTful stores on your grids. If you're going to need batch operations, RESTful stores are not your friends. Sorry.
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