Dojo OnDemandGrid won't display data - javascript

I'm using arcgis javascript api 3.19 which includes dojo. I'm trying to display some data in a grid and edit it. Right now, the data won't display in the grid.
I'm using the tutorial to learn how to use this grid, [http://dgrid.io/js/dgrid/demos/laboratory/][http://dgrid.io/js/dgrid/demos/laboratory/]
I've embedded their sample code in my widget and it doesn't work.
(Rather than include my whole widget, I'll just show the sample code.)
It doesn't find the dgrid/Editor, but it can find dgrid/editor.
The grid header and an empty box for the data shows up, but no data.
require([
'dojo/_base/declare',
'dstore/Memory',
'dstore/Trackable',
'dgrid/OnDemandGrid',
'dgrid/Keyboard',
'dgrid/CellSelection',
'dgrid/Editor' // I have to use dgrid/editor for this to be found
], function (declare, Memory, Trackable, OnDemandGrid, Keyboard, CellSelection, Editor) {
var store = new (declare([Memory, Trackable]))({
data: createData()
});
// Instantiate grid
var grid = new (declare([OnDemandGrid, Keyboard, CellSelection, Editor]))({
collection: store,
columns: {
First_Name: {
label: 'First Name',
editor: 'text'
},
Last_Name: {
label: 'Last Name'
}
}
}, 'grid');
grid.startup();
function createData() {
var data = [];
var column;
var i;
var item;
for (i = 0; i < 50; i++) {
item = {};
for (column in { First_Name: 1, Last_Name: 1 }) {
item.id = i;
item[column] = column + '_' + (i + 1);
}
data.push(item);
}
return data;
}
});

Ok, I found the answer.
Esri has two directories in their javascript api, dgrid and dgrid1.
And the files in them are largely the same (by filename at least)
Apparently the "correct" classes are in dgrid1, not dgrid.
I suppose there might be a good reason for putting the code in a differently named directory than the documentation, but from where I'm sitting, not knowing that reason, I can only say "Thanks for letting me beat my head against a wall for two days on this. Thanks so very much."

Related

Exporting model to csv

I'm trying to make an export of my model which consists out of employees, some properties and a Date.
Visualisation of my model
var myModel= {
employees: [{
pentagram: oMyData.Pentagram,
records: [{
Date: oMyData.Date,
GC: oMyData.Lunch,
CheckIn: oMyData.CheckedIn,
CheckOut: oMyData.CheckedOut
}]
}]
};
Purpose of my application
My app is used to log which employee is in the building by letting them check in and out at the front door. This is registered to a HanaXS database. Each day when an employee checks in, a record is created with the corresponding properties. So if the decide not to eat at the office, they will click on the GC button (which stands for 'no consumption' in dutch).
So in a nutshell. Each employee has their own record per date in the database.
What do I want to do
I want to make an excel sheet which will cover a month.
The most left column will cover the names of the employee's (Pentagram). After that all the columns will be a day in the corresponding month in chronological order.
The content should be an X when they pressed the GC button. Otherwise the cell should be empty.
My problem
I have no clue how to get the dates as columns while keeping the binding with the employees. I've already searched a lot on exporting of the model and of tables but nothing is actually near to what I need.
If anyone has some experience or done this before I would be really gratefull for some help.
Thanks in advance
Hi you can use the following libraries
'sap/ui/core/util/Export',
'sap/ui/core/util/ExportTypeCSV',
This is the sample code you can refer to suit your needs
generateExcel: function(oData, that) {
var oModel = new JSONModel();
oModel.setData(oData); //oData is the model data which is binding to the table
var oTable = this.getViewById("yourTableName").getTable();
var aColumns = oTable.getColumns();
var aItems = oTable.getItems();
var aTemplate = [];
for (var i = 0; i < aColumns.length; i++) {
var oColumn = {
name: aColumns[i].getHeader().getText(),
template: {
content: {
path: null
}
}
};
if (aItems.length > 0) {
oColumn.template.content.path = aItems[0].getCells()[i].getBinding("text").getPath();
}
aTemplate.push(oColumn);
}
var oExport = new Export({
// Type that will be used to generate the content. Own ExportType’s can be created to support other formats
exportType: new ExportTypeCSV({
separatorChar: ",",
charset: "utf-8"
}),
// Pass in the model created above
models: oModel,
// binding information for the rows aggregation
rows: {
path: "/results"
},
// column definitions with column name and binding info for the content
columns: aTemplate
});
oExport.saveFile().always(function() {
this.destroy();
});
}
Hi you can use custom formatter for columns depending on types like below an example
var oColumn = {
name: aColumns[i].getHeader().getText(),
template: {
content: {
path: null,
formatter: function(value) {
if (value instanceof(Date)) {
//Convert to user date format
var oFormat = DateFormat.getDateInstance({
style: "short"
});
value = oFormat.format(value);
} else {
value = (value === null) ? "" : value;
}
return value;
}
}
}
};

Deleting a row using api.updateRowData(transaction) has no effect on data source

I have a custom cell renderer to delete given entity.
function ActionButtonsCellRenderer() {}
ActionButtonsCellRenderer.prototype.init = function(cellRenderParams) {
var tempDiv = document.createElement('div');
var deleteButton = document.createElement("a");
deleteButton.href = "javascript:void(0)";
deleteButton.innerHTML = "<i class='fa fa-trash'></i>";
tempDiv.appendChild(deleteButton);
deleteButton.addEventListener("click",function(){
cellRenderParams.api.updateRowData({remove: [cellRenderParams.data]})
});
this.eGui = tempDiv.firstChild;
};
ActionButtonsCellRenderer.prototype.getGui = function() {
return this.eGui;
};
It actually deletes the row from GUI. No problem there.
But when user adds another row using below logic;
function addRow() {
var row = {t1 : "test"}
dataSource[dataSource.length] = row;
agGridOptions.api.setRowData(dataSource);
}
Deleted row also became visible again in the grid. Which means that the dataSource object is not updated.
What am I doing wrong here ? The dataSource must be updated in my scenario.
Isn't there a two-way binding which I can use ?
For deleting the selected rows use this code,
this.selectedNodes = this.GridOptions.api.getSelectedNodes();
this.GridOptions.api.removeItems(this.selectedNodes);
this.GridOptions.api.refreshView();
Now selected Row will be deleted.
Ag-grid makes a copy of the data that you provide to it. So when you are using updateRowData, ag-grid will update the data that it has, not your original data array. This is good design to avoid unexpected results and loss of original data.
There are two possible solutions to your issue:
mutate your original data anytime you need to update the data - this will likely get really messy really fast
--- OR ---
use the ag-grid's built in functionality of allowing it to update row data, then when you need to do something with the dataSource (such as downloading in an excel or sending to some other function) use the getModel() function to get the data that ag-grid is aware of.
For anyone that come across this post i know its a long time ago but.
I had to add and remove a row from one table to another without UI selection
Lets say we have a grid with common columnDefs e.g. headersName, fields ( its important to have fields) and etc.
We gonna have 2 columns:
{
headerName: 'Name',
field: 'name',
cellRenderer: params => params.data.name,
....
},
{
headerName: 'Age',
field: 'age',
cellRenderer: params => params.data.age,
....
},
What i did was:
const item = {
'name': 'New name',
'age': 25,
}
* Remove a row - if the grid already have this item
this.gridApi.updateRowData({ remove: [item] });
* Add row - if the grid doesn't have it
gridApi2 is your seconds grid table api
this.gridApi2.updateRowData({ add: [item] });
add/remove: [item] - it has to be array
if you need to refresh for some reasons (sometime change detector does't update ) there is 2 AgGrid refresh options: Refresh Cells and Redraw Rows..for this case i will use refreshCells()
this.gridApi.refreshCells({ force: true });
this.gridApi2.refreshCells({ force: true });
used materials: https://www.ag-grid.com/javascript-grid-data-update/
section: Full CRUD & Bulk Updating
method: Method 2 - Transaction
This works for me. Of course here we are assuming that we have a grid working e.g. (gridReady)="onGridReady($event)"

Searching nested object with Elastic Search and Firebase

Following the Flashlight GitHub example by Firebase.com, I got it to work as instructed to deploy on Heroku - but the way my data is structured, I think there might be a better way?
My data structure looks like this:
(root)pages
-->Firebase Unique ID
---->chat
---->content
------>Firebase Unique ID
-------->title
-------->description
-------->filter = article
---------->tags
------------tag 1
------------tag 2
I only want Elastic Search to return results based on matching the tags or the filter = article, but I get everything from pages down (all the chat, all the content regardless if it matched the result, but not content from other pages, etc...)
The path in config.js for the flashlight code is simply:
exports.paths = [
{
path: "pages",
index: "firebase",
type: "pages"
},
{
path: "event_entry",
index: "firebase",
type: "events"
}
];
I'm still early enough in development that I can change the structure of the data; I thought about:
(root) content
-->Firebase Unique ID
---->title
---->description
---->filter = article
And then simply storing the Firebase Unique ID in the pages object somewhere?
As it stands right now, I'm parsing the result as so to check the tags and only show what is actually tagged with what I searched for and it's just... ugly...
function showResults(snap) {
if( snap.val() === null ) { return; } // wait until we get data
var dat = snap.val();
var out = '';
$.each(dat["hits"]["0"]["_source"]["content"], function(i, v) {
for(var k in v.tags)
{
if(v['tags'][k]['text'] == $scope.search)
{
out += v.title + ": " + i + "<br>";
console.log(i);
}
}
});
$("#results").text(out);
}

Loop Through JSON, Insert Key/Value Between Objects?

UPDATE - Thanks for all the great answers and incredibly fast response. I've learned a great deal from the suggested solutions. I ultimately chose the answer I did because the outcome was exactly as I asked, and I was able to get it working in my application with minimal effort - including the search function. This site is an invaluable resource for developers.
Probably a simple task, but I can't seem to get this working nor find anything on Google. I am a Javascript novice and complex JSON confuses the hell out of me. What I am trying to do is make a PhoneGap Application (Phone Directory) for our company. I'll try to explain my reasoning and illustrate my attempts below.
I have JSON data of all of our employees in the following format:
[
{
"id":"1",
"firstname":"John",
"lastname":"Apple",
"jobtitle":"Engineer"
},
{
"id":"2",
"firstname":"Mark",
"lastname":"Banana",
"jobtitle":"Artist"
},
... and so on
]
The mobile framework (Framework 7) that I am using offers a "Virtual List" solution which I need to take advantage of as our directory is fairly large. The virtual list requires you to know the exact height of each list item, however, you can use a function to set a dynamic height.
What I am trying to do is create "headers" for the alphabetical listing based on their last name. The JSON data would have to be restructured as such:
[
{
"title":"A"
},
{
"id":"1",
"firstname":"John",
"lastname":"Apple",
"jobtitle":"Engineer"
},
{
"title":"B"
},
{
"id":"2",
"firstname":"Mark",
"lastname":"Banana",
"jobtitle":"Artist"
},
... and so on
]
I've been able to add key/value pairs to existing objects in the data using a for loop:
var letter, newLetter;
for(var i = 0; i < data.length; i++) {
newLetter = data[i].lastname.charAt(0);
if(letter != newLetter) {
letter = newLetter
data[i].title = letter;
}
}
This solution changes the JSON, thus outputting a title bar that is connected to the list item (the virtual list only accepts ONE <li></li> so the header bar is a div inside that bar):
{
"id":"1",
"firstname":"John",
"lastname":"Apple",
"jobtitle":"Engineer",
"title":"A"
},
{
"id":"1",
"firstname":"Mike",
"lastname":"Apricot",
"jobtitle":"Engineer",
"title":""
}
This solution worked until I tried implementing a search function to the listing. When I search, it works as expected but looks broken as the header titles ("A", "B", etc...) are connected to the list items that start the particular alphabetical section. For this reason, I need to be able to separate the titles from the existing elements and use them for the dynamic height / exclude from search results.
The question: How can I do a for loop that inserts [prepends] a NEW object (title:letter) at the start of a new letter grouping? If there is a better way, please enlighten me. As I mentioned, I am a JS novice and I'd love to become more efficient programming web applications.
var items = [
{ "lastname":"Apple" },
{ "lastname":"Banana" },
{ "lastname":"Box" },
{ "lastname":"Bump" },
{ "lastname":"Can" },
{ "lastname":"Switch" }
];
var lastC = null; //holds current title
var updated = []; //where the updated array will live
for( var i=0;i<items.length;i++) {
var val = items[i]; //get current item
var firstLetter = val.lastname.substr(0,1); //grab first letter
if (firstLetter!==lastC) { //if current title does not match first letter than add new title
updated.push({title:firstLetter}); //push title
lastC = firstLetter; //update heading
}
updated.push(val); //push current index
}
console.log(updated);
Well right now you have an array of objects - prefixing the title as its own object may be a bit confusing - a better structure may be:
[
{
title: "A",
contacts: [
{
"id":"1",
"firstname":"John",
"lastname":"Apple",
"jobtitle":"Engineer",
"title":"A"
}
]
Given your current structure, you could loop and push:
var nameIndexMap = {};
var newContactStructure = [];
for (var i = 0; i < data.length; i++) {
var letter = data[i].lastname.charAt(0);
if (nameIndexMap.hasOwnProperty(letter)) {
//push to existing
newContactStructure[nameIndexMap[letter]].contacts.push(data[i])
} else {
//Create new
nameIndexMap[letter] = newContactStructure.length;
newContactStructure.push({
title: letter,
contacts: [
data[i]
]
});
}
}
newContactStructure will now contain your sorted data.
Demo: http://jsfiddle.net/7s50k104/
Simple for loop with Array.prototype.splice will do the trick:
for (var i = 0; i < data.length; i++) {
if (i == 0 || data[i-1].lastname[0] !== data[i].lastname[0]) {
data.splice(i, 0, {title: data[i].lastname[0]});
i++;
}
}
Demo. Check the demo below.
var data = [
{"lastname":"Apple"},
{"lastname":"Banana"},
{"lastname":"Bob"},
{"lastname":"Car"},
{"lastname":"Christ"},
{"lastname":"Dart"},
{"lastname":"Dog"}
];
for (var i = 0; i < data.length; i++) {
if (i == 0 || data[i-1].lastname[0] !== data[i].lastname[0]) {
data.splice(i, 0, {title: data[i].lastname[0]});
i++;
}
}
alert(JSON.stringify( data, null, 4 ));

Grouping / counting in javascript using underscore.js

I am new to javascript (and to Stack Overflow) and I've encountered a problem I can't seem to solve. I am trying to generate a simple pie chart that shows the number of Projects for each value of Technology in my data. This is the kind of data I am working with:
[Project1, Java]
[Project2, Excel]
[Project3, SAS]
[Project4, Java]
The pie ratio in the example above would be 2:1:1.
The first part of my code loads the data and pushes it to an array, "techArray", that contains [project, tech]. This part works ok - I've verified it in a simplified version of the code.
I then want to group the array "techArray" and count the instances of each tech. To do so I'm using the Underscore library, as follows:
var chartData = [];
var techData = _.groupBy(techArray, 'tech');
_.each(techData, function(row) {
var techCount = row.length;
chartData = push( {
name: row[0].tech,
y: techCount
});
});
The script then renders the chartData array using highcharts. Again, I have verified that this section works using a simplified (ungrouped) version.
There must be an issue with the grouping/counting step outlined above because I am seeing no output, but I simply can't find where. I am basing my solution on the following worked example: Worked example.
If anyone can spot the error in what I've written, or propose another way of grouping the array, I'd be very grateful. This seems like it should be a simpler task than it's proving to be.
countBy could be used instead of groupBy:
var techArray = [
{ project: 'Project1', tech: 'Java'},
{ project: 'Project2', tech: 'Excel'},
{ project: 'Project3', tech: 'SAS'},
{ project: 'Project4', tech: 'Java'},
];
var counts = _.countBy(techArray,'tech');
This will return an object with the tech as properties and their value as the count:
{ Java: 2, Excel: 1, SAS: 1 }
To get the data in the form for highcharts use map instead of each:
var data = _.map(counts, function(value, key){
return {
name: key,
y: value
};
});
This should work
var techArray = [['Project1','Java'], ['Project2', 'excel'], ['Project3', 'Java']];
var chartData = [];
var techData = _.groupBy(techArray, function(item) {
return item[1];
});
_.each(techData, function(value, key) {
var techCount = value.length;
chartData.push({
name: key,
y: techCount
});
});
_.groupBy needs to either get a property name, or a function that returns the value being grouped. There is no tech property of an array, so you cant group by it. But, as our techArray is an array of tuples, we can pass a function _.groupBy that returns the value that we want to groupBy, namely the second item in each tuple.
chartData now looks like this:
[{
name: 'Java',
y: 2
}, {
name: 'excel',
y: 1
}]

Categories

Resources