Struggling to find a bit of code to easily understand.
How do you add a row and clear all rows in a Dojo datagrid (version 1.4.2). Lets say the data is 2 columns with customerID and address.
I am using
dojo.data.ItemFileWriteStore
to store values in - but again not quite sure how this should be used.
It can't be that hard.
Cheers.
You can get the data store reference from the grid using grid.store, then you can use store.newItem() to create a new item in the store. This new item is added as a new row in the grid. For example, store.newItem({customerID : 1, address : "Somewhere"}).
To clear all the rows, you can either loop all the items in the data store and use deleteItem() to remove all the items, or use the internal function _clearData() in data grid to remove all the rows, or use setStore() to set a new empty store to the grid. I prefer to use a empty store to reset the grid.
The above answers are correct, but you also need to call save() on the write store to "commit" the change. When you save, a widget using the store (datagrid for example) will refresh itself.
Also, newItem() returns the new item you just created so if you don't want to pass an object to newItem just modify its return value, then save() the store.
Pseudo code:
var i = store.newItem({});
store.setValue(i,"newattribute1","new value");
store.setValue(i,"newattribute2","new value 2");
store.save();
Here is the relevant docs for ItemFileWriteStore which tell how to use newItem(), setValue(), and save().
Instead of deleteItem, you should use setStore(new ItemFileWriteStore()), but I suspect there is a memory leak when you do this, be careful. This makes a new blank store to be used with the grid.
I have finish one example about this... the code is here
//First we create the buttons to add/del rows
var addBtn = new dijit.form.Button({
id: "addBtn",
type: "submit",
label: "Add Row"
},
"divAddBtn");//div where the button will load
var delBtn = new dijit.form.Button({
id: "delBtn",
type: "submit",
label: "Delete Selected Rows"
},
"divDelBtn");
//Connect to onClick event of this buttons the respective actions to add/remove rows.
//where grid is the name of the grid var to handle.
dojo.connect(addBtn, "onClick", function(event) {
// set the properties for the new item:
var myNewItem = {
id: grid.rowCount+1,
type: "country",
name: "Fill this country name"
};
// Insert the new item into the store:
// (we use store3 from the example above in this example)
store.newItem(myNewItem);
});
dojo.connect(delBtn, "onClick", function(event) {
// Get all selected items from the Grid:
var items = grid.selection.getSelected();
if (items.length) {
// Iterate through the list of selected items.
// The current item is available in the variable
// "selectedItem" within the following function:
dojo.forEach(items, function(selectedItem) {
if (selectedItem !== null) {
// Delete the item from the data store:
store.deleteItem(selectedItem);
} // end if
}); // end forEach
} // end if
});
Related
I have a Feed List for posting comments in my UI5 xml view
<layout:content>
<m:FeedInput post="onFeedPost" class="sapUiSmallMarginTopBottom"/>
<m:List id="feedList" showSeparators="Inner" items="{path: '/table', sorter: {path: 'DATE', descending: true}}">
<m:FeedListItem sender="{MEMBERID}" timestamp="{DATE}" text="{COMMENT}" convertLinksToAnchorTags="All"/>
</m:List>
</layout:content>
I want to not display duplicate comments that have the same text and date, but keep them in the database. My idea was to in the controller iterate over over the items to do this, but I am not sure what to do with the resulting array
var results = [];
var comments = feed.getItems();
for (var n = 0; n < comments.length - 1; n++) {
var contained = false;
for (var m = n + 1; m < comments.length; m++) {
if (comments[n].getText() === comments[m].getText() &&
comments[n].getDate() === comments[m].getDate()) {
comments.pop(m);
contained = true;
if (!results.includes(comments[n])) {
results.push(comments[n]);
}
}
}
if (!contained && !results.includes(comments[n])) {
results.push(comments[n]);
}
}
// replace list items with results array
I can't figure out how to replace the feed list's items with the new array as there is a getItems function but not a setItems function. It occurs to me there is probably a simpler more idiomatic UI5 way to do this but I haven't found it yet.
First off, the correct way to handle this situation is in the OData service. The service should remove the duplicates before sending the data to the client. If we assume, however, that you can't do this server side, then you have some options.
1.) Do not bind the list items to anything. Instead, use the ODataModel to read the data, then filter out duplicates, create a new list item and add it to the list
Read the data using the ODataModel, then pass the results to a method that will filter and add them items to the list
oModel.read("/EntitySet", {
success: function(oResponse) {
this._addCommentsToList(oResponse.results)
}.bind(this)
})
In your method to handle the results, you'll need to do three things -- create a new FeedListItem, set the binding context of the list item, and then add the list item to the list
var aDistinctComments = //use your logic to filter out duplicates
aDistinctComments.forEach(function(oComment) {
//to set the binding context, you'll need the entity key/path
var sCommentKey = oModel.createKey("/EntitySet", oComment)
//create a new binding context
var oContext = oModel.createBindingContext(sCommentKey)
//create a new FeedListItem
var oItem = new FeedListItem({
sender: "{MemberId}",
...
});
//set the context of the item and add it to the list
oItem.setBindingContext(oContext);
oList.addItem(oItem);
})
2.) Bind the list directly to the OData entity set and then when the list receives the data, iterate over the items and hide the duplicates
<List items="{/EntitySet}" updateFinished="onListUpdateFinished"....>
----- onListUpdateFinished ---
var aItems = oList.getItems();
for (var m = n + 1; m < aItems.length; m++) {
//set a boolean, true if duplicate
var bDuplicate = aItems[m].getText() ==== aItems[n].getText() &&
aItems[m].getDate() === aItems[n].getDate();
//set the visibility of the item to true if it is not a duplicate
aItems[m].setVisible(!bDuplicate)
}
3.) Read the data manually, remove duplicates, and stash it in a JSON model, and bind the table to your JSON model path
oModel.read("/EntitySet", {
success: function(oResponse) {
this._addCommentsToJSONModel(oResponse.results)
}.bind(this)
})
You can stash an array of objects in your JSON model, and then bind the table items to that path
var aDistinctComments = // your logic to get distinct comments
oJSONModel.setProperty("/comments", aDistinctComments)
oList.setModel(oJSONModel);
-----
<List items="{/comments"}....>
4.) Bind your list items to your entity set, iterate over the items, and then remove duplicates from the list. I don't recommend this approach. Removing items manually from lists bound to an entity set can lead to trouble with duplicate IDs.
var oItem = //use your logic to find a duplicate list item
oList.removeItem(oItem)
I recommend first handling this server side in the OData service, and if that's not an option, then use option 1 above. This will give you the desired results and maintain the binding context of your list items. Options 2 and 3 will get you the desired results, but depending on your applicaiton, may make working with the list more difficult.
Here is one approach :
Do not directly bind the list to your oData.
You can create a JSON model which will be the resulting model after removing duplicate items.
Bind the JSON model to the List as such:
var oList = this.getView().byId("feedList");
oList.bindAggregation("items", "pathToJsonArray", template);
(The template is feedlistitem in this case).
On my UI, I've a grid where I'm applying filters on columns and getting filtered data. In my REST request, my UI is sending filter as a key:value like this:
filter:[{"operator":"gt","value":222,"property":"qty_raw"}]
and, I want to extract the same filter data from the same grid (using ComponentQuery) so that I can send the same filter/filters(more than one column) in another request on a button click handler, I am writing code in EXTJS like this,
var gridObj = Ext.ComponentQuery.query('myGridId')[0];
var filters = gridObj.store.getFilters();
console.log("print filters.....",filters);
filters in Chrome tool looks like the following snapshot, where the data which I need is in items and map, but I can't reach to the data. I don't know if there is any better way to do this? any suggestions?
Update: I tried doing it using store lastOptions property, it still not working (Error: Uncaught TypeError: Cannot read property 'params' of undefined)
var gridObj = Ext.ComponentQuery.query('Grid_xx')[0];
var lastOptions = gridObj.store.lastOptions,
lastParams = Ext.clone(lastOptions.params);
lastParams.limit = limit; //;var limit = gridObj.store.getTotalCount();
lastParams.page = page; // var page = 1
lastParams.start = start; // var start= 1
lastParams.columnsNameArray = JSON.stringify(columnsNameArray);
console.log("columnArray............ =",lastParams.columnsNameArray);
var encodedFilename = Ext.urlEncode(lastParams);
Ext.create('Ext.Component', {
renderTo: Ext.getBody(),
//url: EfwSlamUI.Config.restUrl.GridExport,
cls: 'x-hidden',
params: lastParams,
autoEl: {
tag: 'iframe',
src: Abc.Config.restUrl.GridExport + '?' + encodedFilename}
});
One suggestion:
I think a better approach would be to use the store.reload() function because it will automatically use the last params used by the last stores request.
https://docs.sencha.com/extjs/6.0/6.0.0-classic/#!/api/Ext.data.BufferedStore-method-reload
You can change the filters / sorters on the grid or store.
https://docs.sencha.com/extjs/6.0/6.0.0-classic/#!/api/Ext.data.BufferedStore-property-lastOptions
If you wanna prevent auto-reload of the grid, if a filter is changed, disable autoLoad of the store.
I m using dgrid store to show the grid (dgrid 0.4). Here is my code
require([
'dojo/_base/declare',
'dojo/Deferred',
'dstore/RequestMemory',
'dstore/QueryResults',
'dstore/Trackable',
'dgrid/Grid',
'dgrid/Selection',
'dgrid/extensions/Pagination',
'dgrid/extensions/DijitRegistry',
'dgrid/extensions/DnD',
'dgrid/Keyboard',
'dgrid/Editor',
'dgrid/extensions/ColumnHider',
'dgrid/extensions/ColumnResizer',
'dgrid/Selector',
'dojo/_base/array'
], function (declare, Deferred, RequestMemory, QueryResults, Trackable, Grid, Selection, Pagination, DijitRegistry, DnD, Keyboard, Editor, ColumnHider, ColumnResizer, Selector, array) {
var grid = new (declare([Grid, Trackable, Selection, Pagination, DijitRegistry, DnD, Keyboard, Editor, ColumnHider, ColumnResizer]))({
collection: store,
// items: store.items,
// query: {PRID: '*'},
columns: getColumns(),
// className: 'dgrid-autoheight',
pagingLinks: 1,
rowsPerPage: 10,
pagingTextBox: true,
firstLastArrows: true,
pageSizeOptions: [10, 15, 20,25],
loadingMessage: 'Loading data...',
noDataMessage: 'No results found.',
}, 'grid');
//grid.renderArray(data);
alert(store);
grid.startup();
alert(store);
});
I want to know whether it is possible to store the value of grid in some variable or is there any way to show the entire grid in console or print in console.log.
I tried to alert the store but it shows object. Is there any way to get that object and store it in the array of object?
If you're just asking how to read all of the items from the store, the simplest way would be something like this:
store.forEach(function (item) {
console.log(item);
});
Note that this implicitly fetches all items from the store, which is fine for in-memory stores (since they already have all of their data loaded before you ever fetch regardless), but you probably wouldn't want to do it with e.g. Request or Rest with a large data set.
If you're interested in accessing only the items that are currently rendered in the grid, there's not really a specific way in mind to do it, but you could do something like this (where query is dojo/query):
var rows = query('.dgrid-row', grid.contentNode);
var length = rows.length;
for (var i = 0; i < length; i++) {
console.log(grid.row(rows[i]).data);
}
I am unfamiliar with the stores you're using but going off what Ken said, you could use console.table(data) to avoid looping and to get a nicer format. Some stores you can do something like console.table(store.query());.
I have an ng-repeat in a table. There are several of these tables inside a larger table. Each row has buttons for "add another" (which I have working) and remove current row/move row up-down (which I don't).
They are created with an array, each group in the table has its own array, with one member to start.
vm.choices1 = [{ id: 'choice1' }];
vm.choices2 = [{ id: 'choice1' }];
vm.choices3 = [{ id: 'choice1' }];
Clicking the plus button passes the current array and pushes a new item onto it, thus adding a repeater.
vm.addNewChoice = function(arr) {
var newItemNo = arr.length + 1;
arr.push({
'id': 'choice' + newItemNo
});
};
This works fine. Of course, now I have been asked to add the delete button and up/down buttons.
I get in concept what I need to do: I suppose somehow when the delete button is clicked I need to pass that index number to a delete function and pop that index from the array thats passed:
vm.deleteChoice = function(arr) {
arr.splice(index, index+1); //??
};
But I'm not sure how to get and pass the clicked index to the function. I used to know how to do this in jQuery, but not in Angular. If I can get the index of the clicked item into my function, I'm sure I can figure out the u/down buttons from there too.
Basic punker: http://plnkr.co/edit/WPdnmYbDSXC0LsbeMduM?p=preview
The directive ng-repeat creates a scope for every item that it iterates through. Part of the data assigned to this scope is the attribute $index which will be equal to the index in the array of the item/object.
Source: https://docs.angularjs.org/api/ng/directive/ngRepeat
I am building a rallygrid to display parent level stories. For each row, I want to iterate all the children of that story and pull some information from each child story. e.g.
Ext.Array.each(data, function(record) {
//Perform custom actions with the data here
//Calculations, etc.
recName=record.get('Name');
if (recName.search(/\[Parent\]/i) != -1) {
// Grab Child Iterations
if (record.get('Children').length) {
var childlist = record.get('Children');
for (var child in childlist) {
// I want to get each child's Iteration !!!
}
} else {
childIter = "none";
}
records.push({
FormattedID: record.get('FormattedID'),
ScheduleState: record.get('ScheduleState'),
Name: recName,
NumChildren: record.get('Children').length,
PRDNumber: record.get('PRDNumber')
});
}
});
But, the record.get('Children') retuns objects that look like:
_rallyAPIMajor "1"
_rallyAPIMinor "34"
_ref "https://rally1.rallydev.com/slm/webservice/1.34/hierarchicalrequirement/7272142216.js"
_refObjectName "[Comp] User Story"
_type "HierarchicalRequirement"
I'm assuming there's some Ext call that will take the _ref URI, download it and parse out the JSON into a nice object I can start doing childrecord.get('field') on, but for the life of me, I can't find the right function to call.
You can use the load method of the record's model to retrieve a specific item as mentioned in this question/answer:
Rally App2.0 - Retrieve a specific story
In your case you can get the model from the existing record:
var model = record.self;
model.load(child.get('ObjectID'), {
//options
});
However in your case if you're just looking for some info on each child story's iteration you can probably just include it in the fetch of your initial WsapiDataStore used to load the parent:
fetch: ['Children', 'Iteration', 'StartDate', 'EndDate']