I am updating cells of dataTable very frequently using id as selector as each table cell that has to be updated already has unqiue id assigned. Below is the code
agentStatSocket.onmessage = function(e){
data = JSON.parse(e.data)
//console.log(data);
for(var i=0; i<data.length; i++){
try {
var inboundTd = data[i]['id'] + '-inbound';
var outboundTd = data[i]['id'] + '-outbound';
if (data[i]['inboundCalls'] != 0) {
document.getElementById(inboundTd).innerHTML = data[i]['inboundCalls'];
}
if (data[i]['outboundCalls'] != 0) {
document.getElementById(outboundTd).innerHTML = data[i]['outboundCalls'];
}
} catch (error) {
console.log(data[i]);
}
}
};
I am getting Uncaught TypeError: document.getElementById(...) is null but that id is available in the dom.
I tried to catch error so that at least my loop shouldn't stop and i can get all that data using console.log(data[i) which is not present in the table. To my surprise there were at least 10 objects printed in console. This cannot happen because i can see the previous data is present in table. When i commented out the DataTable() function and reloaded the page i didn't see any error.
Can you please tell me how to update table cells in DataTable as i need Search , Sort and Pagination functionality of DataTable ?
Related
Using the Office JavaScript API, I am trying to fill a selected table using the following code:
Word.run(function (context) {
var table = context.document.getSelection().parentTable;
context.load(table);
return context.sync()
.then(function () {
if (table.isNullObject == true || !table) {
console.log("selection ist not table");
errorHandler("selection is not a table");
} else {
// loop over table
for (var row = 0; row < table.values.length; row++) {
for (var column = 0; column < table.values[row].length; column++) {
console.log(table.values[row][column]);
table.values[row][column] = "Test " + row + " " + column;
}
context.sync().then(function () {
console.log("done");
}).catch(function (e) {
console.log(e);
});
}
}
});
});
The scripts runs fine, the table object exists, the values are logged and the final "done" too. But the table stays as it is - no update of the values. What am I missing?
A few comments about the code you've posted:
Checking for isNullObject on the table object like your code is doing is not effective, because the lines above that will have already thrown an error if the parentTable doesn't exist.
Error handling (catch statement) should be located immediately after the Word.run -- that way it'll catch any error that occurs inside the Word.run.
Instead of loading the entire table object like you are, you should only load the properties that you need (in this case, values and rows/items/cells/items/body).
To set a cell value, use the insertText method on the body of the cell that you want to update.
The following code sample incorporates this feedback, and should successfully update the values in your table.
Word.run(function (context) {
var table = context.document.getSelection().parentTable;
table.load("values, rows/items/cells/items/body");
return context.sync()
.then(function () {
for (var row = 0; row < table.values.length; row++) {
for (var column = 0; column < table.values[row].length; column++) {
console.log(table.values[row][column]);
table.rows.items[row].cells.items[column].body.insertText("Test " + row + " " + column, "Replace");
}
}
return context.sync()
.then (function() {
console.log("Done");
});
});
}).catch(function (e) {
console.log(e);
});
Great question #BernhardWebstudio! To explain why your specific code doesn't work is because the add-in code is invoked in a separate process from the Office Application and it must make 'requests' to actually acquire the data. This is similar to asking for attributes within a REST or OData call. (e.g. $select)
What does this mean for you? Well with a just slight alteration to your code you just need to request what properties of the table you want to load. Since you only care about the values of the table, it would be easy to do this with this type of code. If you notice I also have a commented out line that is table.load("[Property Name]"); to use the Office Apps Object model as proxy objects as well. Kim has pointed out some other really good suggestions as well. Cheers and Happy Coding!
Word.run(function (context) {
let table = context.document.getSelection().parentTable;
//table.load("values");
context.load(table, "values");
//...
I'm trying to migrate my tiny report from V3 to V4, but I have found an issue which is annoying me and making me feel like I'm totally dumb.
So I just took the example code at https://developers.google.com/analytics/devguides/reporting/core/v4/quickstart/web-js
and change a couple of things, and it works, it runs the report. But when I try to retrieve the data from the different rows with the below function:
function displayResults(response) {
var Objeto = response.result["reports"];
var Filas01 = Objeto["data"];
console.log(Objeto);
console.log(Filas01);
}
Objeto shows everything within .reports
But Filas01 shows undefined, I have tried to retrieve reponse.results.reports.data.rows;
And several variations but it says undefined all the time,
I have no clue why it was working on V3 and is not on V4,
Please any help would be much appreciated :)
There are samples of how to make requests and precess the response in various languages. But specifically here is a simple JavaScript function which processes the results into a table:
function handleReportingResults(response) {
if (!response.code) {
outputToPage('Query Success');
for( var i = 0, report; report = response.reports[ i ]; ++i )
{
output.push('<h3>All Rows Of Data</h3>');
if (report.data.rows && report.data.rows.length) {
var table = ['<table>'];
// Put headers in table.
table.push('<tr><th>', report.columnHeader.dimensions.join('</th><th>'), '</th>');
table.push('<th>Date range #</th>');
for (var i=0, header; header = report.columnHeader.metricHeader.metricHeaderEntries[i]; ++i) {
table.push('<th>', header.name, '</th>');
}
table.push('</tr>');
// Put cells in table.
for (var rowIndex=0, row; row = report.data.rows[rowIndex]; ++rowIndex) {
for(var dateRangeIndex=0, dateRange; dateRange = row.metrics[dateRangeIndex]; ++dateRangeIndex) {
// Put dimension values
table.push('<tr><td>', row.dimensions.join('</td><td>'), '</td>');
// Put metric values for the current date range
table.push('<td>', dateRangeIndex, '</td><td>', dateRange.values.join('</td><td>'), '</td></tr>');
}
}
table.push('</table>');
output.push(table.join(''));
} else {
output.push('<p>No rows found.</p>');
}
}
outputToPage(output.join(''));
} else {
outputToPage('There was an error: ' + response.message);
}
}
I would also recommend taking the time to review the overal structure of the response in the reference docs
I have created an event so that I can add listeners for when an event occurs. There will be different scenarios that trigger the event and therefore would be tracking what triggered the event and handle it appropriately. However, I tried adding the dispatchEvent within a function that occurs within a loop and I am receiving an InvalidState error. Anyone cares to explain what causes this error and why it is happening here. You can see my code below
//create event
var event = new Event('tableRowAdded');
//get element reference
var table = document.getElementById('dataTable');
//set model
var model = [{jsonData},{jsonData},{jsonData}];
//validate model and then start creating table
function addRowsToTable(DOMTable, rowData){
//stop execution if rowdata null
if(rowData == null || DOMTable == null){
return;
}
var currentRowCount = DOMTable.rows.length;
//add empty row to table
var tr = DOMTable.insertRow(currentRowCount);
tr.id = "data_row_" + currentRowCount;
//add columns to table
//first cell is used for error data
var td = tr.insertCell(0);
//traineeCode
td = tr.insertCell(1);
td.innerHTML = rowData.TRAINEE_CODE; //this is one of the json keys within the json data
}
function populateTableFromJSON(){
var count = model.length;
//loop over json array to populate table
for(i = 0; i < count; i++){
addRowsToTable(table, model[i]);
//dispatch event occured
table.dispatchEvent(event);
}
}
This is the error received
Uncaught InvalidStateError: Failed to execute 'dispatchEvent' on 'EventTarget': The event is already being dispatched.
Presumably you need to change:
table.dispatchEvent(event);
to
table.dispatchEvent(new Event('tableRowAdded'));
Very messed up the example you posted.
You're calling a method where you perform object validation:
if(rowData == null || DOMTable == null){
return;
}
but at the same time you're ignoring the validation trying to dispatch the event anyway on the next line:
table.dispatchEvent(event);
The event object in javascript have some properties changed after being dispatched that's because the event should reflect its current state at several phases. Try to call this way:
table.dispatchEvent(new Event('tableRowAdded'));
I know this question is a little dated, but I thought I would at least answer it incase someone else stumbles upon this post.
The reason you are getting the error is because you are trying to dispatch the event to the same object (the table) over and over again. Try dispatching it to each row.
EDIT: Here's your code modified. I moved the dispatch inside the loop where the rows are added and added an event listener to the table.
//create event
var event = new Event('tableRowAdded');
//get table
var table = document.getElementById('dataTable');
// set event listener
table.addEventListener("tableRowAdded", function(e) {
handler code
});
//set model
var model = [{jsonData},{jsonData},{jsonData}];
//validate model and then start creating table
function addRowsToTable(DOMTable, rowData){
//stop execution if rowdata null
if(rowData == null || DOMTable == null){
return;
}
var currentRowCount = DOMTable.rows.length;
//add empty row to table
var tr = DOMTable.insertRow(currentRowCount);
tr.id = "data_row_" + currentRowCount;
//add columns to table
//first cell is used for error data
var td = tr.insertCell(0);
//traineeCode
td = tr.insertCell(1);
td.innerHTML = rowData.TRAINEE_CODE; //this is one of the json keys within the json data
// dispatch event
tr.dispatchEvent(event);
}
function populateTableFromJSON(){
var count = model.length;
//loop over json array to populate table
for(i = 0; i < count; i++){
addRowsToTable(table, model[i]);
}
}
I have a ribbon button command which executes a javascript function and passes in the selected rows in a grid. I am looping through that list to create a $select filter to make a RetrieveMultiple request.
The problem is everytime I get the following error
400: Bad Request: No Property 'id' exists in type 'Microsoft.Xrm.Sdk.Entity' at position 1
I have tried with id instead of Id but I still get the same error.
My code is below
function approveMultipleApplications(selectedApplicationReferences) {
if (selectedApplicationReferences && selectedApplicationReferences.length > 0) {
var filter = '';
for (var i = 0; i < selectedApplicationReferences.length; i++) {
filter += '(id eq guid\'' + selectedApplicationReferences[i].Id + '\')';
if (i < selectedApplicationReferences.length - 1) {
filter += ' or ';
}
}
var options = "$select=new_assessmentcount,new_requiredassessmentcount&$filter=" + filter;
try {
SDK.REST.retrieveMultipleRecords("new_application", options, retrieveApplicationsCallBack, function (error) {
alert(error.message);
}, retrieveComplete);
}
catch (ex) {
Xrm.Utility.alertDialog('Something went wrong, please try again or contact your administrator ' + ex, null);
}
}
else {
Xrm.Utility.alertDialog('You must select at least one application to approve', null);
}
}
The selectedApplicationReferences[i].Id is in this format {guid-value}
Any help or guidance is appreciated
The error message is pretty much spot on: Use LogicalNameId instead of just Id. In your case that would be new_applicationId:
filter += '(new_applicationId eq guid\'' + selectedApplicationReferences[i].Id + '\')';
It can be a bit confusing since there is actually no Id-field in the database. If you use e.g. early bound classes, the Id field is set for you behind the scenes, so that might have confused you. The Id field is not returned by the OData endpoint.
I got a table with remote datasource. in one cell I got the userID. Because I want to show the username instead of the user ID I made a custom template function:
function getUserName(pmcreator){
var user = '';
var data = ''
ds_userList.fetch(function(){
var data = this.data();
for(var i = 0, length = data.length; i < length; i++){
if(data[i].uID == pmcreator){
console.log(data[i].uLastname)
user = data[i].uLastname
}
}
});
return user
}
But its not working as it should, the cells stay empty. I got no errors but I see that the remote request to fetch the usernames is not completed before the grid is filled out. I thought the custom function of fetch is waiting for the results to return but it don't seems so.
Any Idea? I find thousends of examples but all with static local data. I need one with both remote, the grid conent and the template data.
This is probably due the fact that when yuo call the dataSource.fetch it fires off an async function, which causes the thread running the template to continue on. According to kendo you will need to return a control, then set the content of that control inside the callback.
Quick sample using Northwind categories...
Here is the template function
function getDetails(e) {
$.getJSON("http://services.odata.org/V3/Northwind/Northwind.svc/Categories", null, function(data) {
var category = data.value.filter(function(item, i) {
return item.CategoryID === e.CategoryID;
});
$("#async_" + e.CategoryID).html(category[0].Description);
});
return "<div id='async_" + e.CategoryID + "'></div>";
}
http://jsbin.com/ODENUBe/2/edit
I kept getting a recursive error maximum call stack when I just tried to fetch the dataSource, so I switched to a simple getJSON, but it should work pretty much the same.