Extjs 4.2 store.getRange gives data of previously loaded store - extjs

I have an extjs store associated with grid class. when I select a class, it gives ClassID of the record.
var ClassData = record.get('ClassID');
console.log(ClassData);
Based on this ClassID I am loading store of next grid:
var Grid = this.getSemGrid();
var Store = Grid.getStore(); // your grid's store
//load store with records having selected class ID
var g = Store.load( {params : {ClassID: ClassData }});
Till here everything is fine.
Once the store is loaded, I am getting all loaded records (Error Area)
var selected = g.getRange(); // getRange = select all records
Then pushing all the values of one field of all records in an array
var Excerpt = []; // start with empty array
Ext.each(selected, function(item) {
// add the fields that you want to include
var Obj = {
third_field: item.get('ExamName')
};
Excerpt.push(Obj); // push this to the array
}, this);
console.log(Excerpt);
Excerpt gives array of previously selected record not the current record.
I have also tried
Store.loadData([],false);
to clear all the loaded data of store before loading it again.

Got this working
var g = Store.load({
params : {ClassID: ClassData },
callback : function(records, operation, success){
var Excerpt = []; // start with empty array
Ext.each(records, function(item) {
// add the fields that you want to include
var Obj = {
third_field: item.get('ExamName')
};
Excerpt.push(Obj); // push this to the array
}, this);
}
});

Related

Doc with ObjectId Array - push value if exists, remove otherwise

I'm new to MongoDB and mongoose.
So my model holds many fields, amongst them is an Array of ObjectIDs
var modelSchema = new Schema({
//...
inner_array: [Schema.Types.ObjectId],
//...
});
What I'm trying to achieve with my query is:
Find a model by it's Id,
If the inner array contains a specific value remove it from the array.
If the value is not within the inner_array, push it
var target_id = // document id
var inner_object_id = // value to push
models.MyModel.findOne(
{_id: target_id},
function (err, model) {
// IN THIS SCOPE 'INNER_OBJECT_ID' IS UNDEFINED
// if model.inner_array contains 'inner_object_id', remove it
// otherwise, push 'inner_object_id' into model.inner_array
model.save();
res.json(model); // return modified document to client
}
);
I believe this can be written in a single findOneAndUpdate, but I can't figure out the syntax..
Thanks alot!
I believe you can achieve that using MongooseArray.pull and MongooseArray.addToSet
var target_id = // document id
var inner_object_id = // value to push
models.MyModel.findOne({
_id: target_id
}, function (err, model) {
if (model.inner_array.indexOf(inner_object_id) !== -1) {
model.inner_array.pull(inner_object_id);
} else {
model.inner_array.addToSet(inner_object_id);
}
model.save();
res.json(model); // return modified document to client
}

How to remove the summary grouping of particular row in EXTJS

If I apply groupField property in the grid and store, extjs will automatically sort records by groupField.
For example: http://dev.sencha.com/deploy/ext-4.0.0/examples/grid/group-summary-grid.html, it used 'project' as groupField.
My Question is How can I add an extra row, which does not belong to any group, into a grid with groupField. (Like this: http://i59.tinypic.com/30s973l.jpg)
By default group is made for each value from groupField, also for empty groupField (but it appears first). If it is enough for you then you don't have to do anything.
Fiddle: http://jsfiddle.net/tme462tj/
When you want to have behavior like on attached image, then some work has to be done.
To put empty value at the end, you can create convert function for model field (eg: convert: function(v) { return v ? v : defaultDepartment; }). If you want to hide header and summary for this empty group, you can attach event listener to viewready event and hide them using styles:
viewready: function() {
var els = this.getEl().query('.x-grid-group-hd');
els = Ext.Array.filter(els, function(e) { return e.textContent.trim() == defaultDepartment; });
if (els.length !== 1) {
return;
}
var header = Ext.fly(els[0]);
header.setStyle('display', 'none');
var summary = header.up('.x-group-hd-container').down('.x-grid-row-summary');
if (summary) {
summary.setStyle('display', 'none');
}
}
Fiddle: http://jsfiddle.net/hdyokgnx/1/
As per my comment on the accepted solution, this revision makes the grouping header hide permanently for the duration of that grid view.
This solves my problem of needing a grouping grid but with one group that does not have a group header row.
store.load
({
params :
{
arg1 : 1
,arg2 : '2'
}
,callback : function( records, operation, success )
{
var els = me.theGrid.getEl().query('.x-grid-group-hd');
els = Ext.Array.filter( els, function(e)
{
return e.textContent.trim().includes( "*** A SUBSTRING IN GROUPING FIELD ***" );
});
if (els.length !== 1)
{
return;
}
var header = Ext.fly(els[0]);
header.setStyle('display', 'none');
var summary = header.up('.x-group-hd-container').down('.x-grid-row-summary');
if (summary)
{
summary.setStyle('display', 'none');
}
}
});

IndexedDB key generator resets after put-transaction

This problem has me stumped.
For some reason, the autoincrementing key generator in indexedDB resets after performing and update on an existing object with a put-transaction, leading to overwrites of data in the database.
For my app, I'm using a self written IndexedDB service for angularJS with all the basic CRUD functions implemented.
I may also add that I'm developing with Ionic Framework, even though I doubt that is to blame.
Considering the service is a work-in-progress, I've let the key path for an object store default to "id" with an autoincrementing strategy.
The indices for the given store, nevertheless, are up to the user to decide in a specific object.
As an example:
dbHelper.objectStores = [{'employees',
indices: [{indexName: 'name', isUnique: false},
{indexName: 'phone', isUnique: true}]}];
This would, unless already created in the db, create the object store 'employees' with indices 'name' and 'phone', where 'phone' would have to be a unique value while 'name' would not.
Here is the implementation of the openDB function.
Please note that dbHelper.objectStores is supposed to be empty as it's up to the user to assign these properties before opening the db(or else it is defaulted).
angular.module('dbProvider', [])
.factory('$db', ['$window', function($window) {
// DB Object
var dbHelper = {};
// Properties - Are given defaults unless assigned manually by user before openDB is invoked.
dbHelper.dbName = 'defaultDB';
dbHelper.dbVersion = 1;
dbHelper.objectStores = [];
dbHelper.openDB = function(onCompleteCallback, onErrorCallback) {
console.log('Atempting to open db with name ' + dbHelper.dbName + '.');
var request = $window.indexedDB.open(dbHelper.dbName, dbHelper.dbVersion);
// Invoked by indexedDB if version changes
request.onupgradeneeded = function(e) {
console.log('Version change. Current version: ' + dbHelper.dbVersion);
var db = e.target.result;
e.target.transaction.onerror = onErrorCallback;
if(dbHelper.objectStores.length === 0) {
dbHelper.objectStores.push({name:'defaultStore', indices: []});
}
for(var store in dbHelper.objectStores) {
if(db.objectStoreNames.contains(dbHelper.objectStores[store].name)) {
console.log(dbHelper.objectStores[store].name + ' deleted.');
db.deleteObjectStore(dbHelper.objectStores[store].name);
}
var newStore = db.createObjectStore(dbHelper.objectStores[store].name, {keyPath: "id", autoIncrement: true});
for(var index in dbHelper.objectStores[store].indices) {
newStore.createIndex(dbHelper.objectStores[store].indices[index].indexName,
dbHelper.objectStores[store].indices[index].indexName,
{unique : dbHelper.objectStores[store].indices[index].isUnique});
}
console.log(dbHelper.objectStores[store].name + ' created.');
}
};
request.onsuccess = function(e) {
console.log('DB ' + dbHelper.dbName + ' open.');
dbHelper.indexedDB.db = e.target.result;
onCompleteCallback();
};
request.onerror = onErrorCallback;
};
Here are some of the CRUD functions(the ones in question):
dbHelper.findItemWithIndex = function(keyValue, storename,
onCompleteCallback,onErrorCallback) {
var db = dbHelper.indexedDB.db;
var trans = db.transaction([storename], "readwrite");
var store = trans.objectStore(storename);
var index = store.index(keyValue.key);
index.get(keyValue.value).onsuccess = function(event) {
onCompleteCallback(event.target.result);
};
};
dbHelper.addItemToStore = function(item, storename,
onCompleteCallback, onErrorCallback) {
var db = dbHelper.indexedDB.db;
var trans = db.transaction([storename], "readwrite");
var store = trans.objectStore(storename);
var request = store.add(item);
trans.oncomplete = onCompleteCallback;
request.onerror = onErrorCallback;
};
dbHelper.deleteItemFromStore = function(itemId, storename,
onCompleteCallback, onErrorCallback) {
var db = dbHelper.indexedDB.db;
var trans = db.transaction([storename], "readwrite");
var store = trans.objectStore(storename);
var request = store.delete(itemId);
trans.oncomplete = onCompleteCallback;
request.onerror = onErrorCallback;
};
dbHelper.updateItem = function(item, storename, onCompleteCallback, onErrorCallback) {
var db = dbHelper.indexedDB.db;
var trans = db.transaction([storename], "readwrite");
var store = trans.objectStore(storename);
var request = store.put(item);
trans.oncomplete = onCompleteCallback;
request.onerror = onErrorCallback;
};
Finally, the code from the controller where the transactions are invoked.
The strategy here, is that the item is added to the db using the addItemToStore function the first time it is persisted, and then afterwards the updateItem function.
After adding the first time, the object is immediately fetched in order to keep working on it with the assigned id from the db.
$scope.updateTemplate = function() {
console.log('Saving..');
var onCompleteCallback = {};
if(!$scope.formTemplate.firstSave) {
onCompleteCallback = $scope.updateModel;
} else {
$scope.formTemplate.firstSave = false;
onCompleteCallback = $scope.setId;
}
$db.updateItem($scope.formTemplate, $scope.objectStore.name,
onCompleteCallback, $scope.dbError);
};
$scope.newItem = function() {
$db.addItemToStore($scope.formTemplate, $scope.objectStore.name,
$scope.setId, $scope.dbError);
};
$scope.setId = function() {
$db.findItemWithIndex(
{key: 'title',
value: $scope.formTemplate.title},
$scope.objectStore.name,
function(result) {
console.log(JSON.stringify(result));
$scope.formTemplate = result;
},
function(error) {
$scope.dbError(error);
});
}
It's here everything goes to hell.
I add an object, go back to another view and find it in the list with id=1.
I add another object, go back to the list view, and there it is with id=2.
And so forth and so forth..
Then, after updating either of the objects with the $scope.updateTemplate function, which also works like a charm, things get interesting:
The next object added gets id=1 and totally erases good old numero uno from earlier.
The next objects also get id's that cause them to replace the already existing objects.
What could cause this?
For testing I'm using Safari 8 in OS 10.10 and I'm deploying to an LGG2 with KitKat 4.4.2.
To be honest, I skimmed, but I saw this, "Safari 8" - the latest iOS and Safari have serious bugs with IndexedDB: http://www.raymondcamden.com/2014/9/25/IndexedDB-on-iOS-8--Broken-Bad
In iOS9, many of the IndexedDb bugs are fixed, but not all. We are currently testing on iOS9 Beta 2 and this particular bug that you found is not fixed.
We were able to work around this problem by not using autoincrement on our object stores. We just manually find the max key value and increment that.
Inserting an object looks something like this:
var store = db.transaction([entity], "readwrite").objectStore(entity);
store.openCursor(null, "prev").onsuccess = function (event) {
var maxKey = event.target.result.key || 0;
object.id = maxKey + 1;
store.add(object);
}

How to load values into multiple text areas based on value from first column in spreadsheet- Google Script?

I need to create an application in Google Script that can read values from a spreadsheet and load those values into text areas based on the value of the first column. For example, in the first column I have NickNames, on the second first name, on the third last name, on the fourth stop date. I have managed to load the nicknames into a listbox using getRange. But I need to know how to load the adjacent values (first, last, stop date) according to NickName into text areas. After the click of a button these values will be updated without creating a new record. Let me know. It would be of great help.
Here is the code I have so far. I need to load values into the corresponding text fields based on the nickname chosen from the dropdown box:
function doGet() {
var app = UiApp.createApplication();
var abspanel= app.createAbsolutePanel();
var stackpanel=app.createStackPanel();
var grid3=app.createGrid(12,12).setId('grd3');
var loadbtn= app.createButton('Load Employee Data');
var selectlbl=app.createLabel('Select Employee');
var active= SpreadsheetApp.openById('0Ai21cbl').getSheetByName('testing');
var endrow= active.getLastRow()-1;
var emplist=app.createListBox().setId('emps').setName('elist');
var emprange= active.getRange('A2:F100').getValues().sort();
for(var i=0; i<emprange.length; i++){
emplist.addItem(emprange[i][0])
}
var efirstlabel=app.createLabel('First').setId('elabel');
var efname=app.createTextArea().setId('efirst').setHeight('20px').setName('efst');
var elastlabel=app.createLabel('Last').setId('ellabel');
var elname=app.createTextArea().setId('elast').setHeight('20px').setName('elst');
var enicklabel=app.createLabel('NickName').setId('enlabel');
var enname= app.createTextArea().setId('enick').setHeight('20px').setName('enk');
var eattlabel= app.createLabel('Employee Attribute').setId('ealabel').setHeight('20px');
var eatt1='TLYDYE'
var eatt2='TLYDNE'
var eatt3='TLNDYE'
var eatt4='TLNDNE'
var eatt5='CAYDYE'
var eatt6='CAYDNE'
var eatt7='CANDYE'
var eatt8='CANDNE'
var eattlist=app.createListBox().setWidth('120px').setId('eattribute').setName('eattbt')
eattlist.addItem(eatt1);
eattlist.addItem(eatt2);
eattlist.addItem(eatt3);
eattlist.addItem(eatt4);
eattlist.addItem(eatt5);
eattlist.addItem(eatt6);
eattlist.addItem(eatt7);
eattlist.addItem(eatt8);
var estartlabel=app.createLabel('Start Date:');
var estartdate=app.createDateBox().setId('edate');
var estoplabel=app.createLabel('Stop Date:');
var estopdate=app.createDateBox().setId('sdate');
var inlabel=app.createLabel().setId('indexlabel');
//Edit Employee Handler
var loadhandler=app.createServerClickHandler('loadEmp');
loadhandler.addCallbackElement(stackpanel);
loadbtn.addClickHandler(loadhandler);
grid3
.setWidget(1,1,selectlbl)
.setWidget(1,2,emplist)
.setWidget(1,3,loadbtn)
.setWidget(2,1, efirstlabel)
.setWidget(2,2, efname)
.setWidget(2,3, elastlabel)
.setWidget(2,4, elname)
.setWidget(3,1, enicklabel)
.setWidget(3,2, enname)
.setWidget(4,1, eattlabel)
.setWidget(5,1,eattlist)
.setWidget(6,1,estartlabel)
.setWidget(7,1,estartdate)
.setWidget(8,1,estoplabel)
.setWidget(9,1,estopdate)
.setWidget(10,1,inlabel);
stackpanel.add(grid3, 'Edit Employee').setStyleAttribute("text-align", "center")
app.add(abspanel)
app.add(stackpanel)
return app;
}
function loadEmp(e){
var app=UiApp.getActiveApplication();
app.getElementById('efirst').setValue(e.parameter.elist);
return app;
}
Well, I guess it's easier if when adding each name to the list you add as the value to return the row number instead omitting and have just the name. This way it will be easier (i.e. you won't need to search for it) to reload the values on the loadEmp handler. e.g.
function doGet() {
//... the starting code your already have
var emprange = active.getDataRange().getValues(); //sorting a matrix doesn't make sense
//also, it's easier if you sort by the desired column the on the spreadsheet before hand
for( var i = 1; i < emprange.length; ++i )
emplist.addItem(emprange[i][0], i); //this 2nd parameter "i" is the return value
//... rest of your code
}
function loadEmp(e) {
var app = UiApp.getActiveApplication();
var active = SpreadsheetApp.openById('0Ai21cbl').getSheetByName('testing');
var index = +e.parameter.elist;
var empdata = active.getRange(index+1, 1, 1, 6).getValues()[0];
var cols = ['efirst','elast','enick']; //in the same order as in the spreadsheet
for( var i = 0; i < cols.length; ++i )
app.getElementById(cols[i]).setValue(empdata[i]);
return app;
}
It's the same thing for the save button, you'll just setValues instead of get.

Extjs4 save all grid data in a table

I know how to get a value from a selected row of a grid, just like this:
var records = Ext.getCmp('My_Grid').getSelectionModel().getSelection();
var record = records.length === 1 ? records[0] : null;
alert(record.get('name'));
But what I want is to get the name of all rows of the grid. To do it, I have used the method above, to write this functional function:
var MonTableau = new Array();
for (var j=0; j<=Ext.getCmp('My_Grid').getStore().getCount()-1; j++) {
Ext.getCmp('My_Grid').getView().select(j);
var records = Ext.getCmp('My_Grid').getSelectionModel().getSelection();
var record = records.length === 1 ? records[0] : null;
MonTableau[j+1]=record.get('name');
}
But it's not professional, I want more simple and professional method.
The ExtJS store provides an each function which applies a passed fn for each record cached (already loaded) in the store:
var myStore = Ext.getCmp('My_Grid').getStore();
myStore.each(function(rec) {
console.log(rec.get('name'));
});
P.S. I'm using console.log(); rather than alert(); as I think it's easier to read everything from the browser log.

Resources