Hi I am getting this warning message even though the results are showing in rows
DataTables warning (table id = 'list'): DataTables warning: JSON data from server could not be parsed. This is caused by a JSON formatting error
while trying to invoking a web service call using angularjs and loading the results in Datatable.Here is my controller.js
var clustersApp = angular.module('clustersApp', []);
clustersApp.controller("nodeListCtrl", function ($scope, $http) {
$http.get('http:demo.json').then(function(res){
$scope.listData = res.data.nodes;
});
});
and datatable js
$(document).ready(function () {
$("#list").dataTable({
"sPaginationType":"full_numbers",
"bFilter": true,
"bInfo": true,
"bServerSide": true,
"oLanguage": {
"sSearch": "",
},
"fnPreDrawCallback": function(oSettings,json) {
$('.dataTables_filter input').addClass('form-control input-sm');
$('.dataTables_filter input').attr('placeholder', 'Enter Ip to search');
},
"asStripClasses": [],
"aoColumnDefs": [{
"bSortable": false,
"aTargets": ["no-sort"]
}]
});
});
Can any one please let me know why is it showing the error.Am very new to JSON.Please help me in sorting the issue.
Related
I have a chart on one of my views in my one page app using angular-chart.js http://jtblin.github.io/angular-chart.js/. The issue is that the chart won't load when the view initializes because the data hasn't yet loaded via the API in the factory. No matter how long I stay on that view, the data won't populate. However, if I go to a different view on the one page app, and come back, the data is there, since it has already loaded in the factory.
It's my understanding that once the data is loaded from factory, that the chart should update immediately because of data bindingl, but why won't it do this on the first view?
Factory (where the data is loaded via service.getChartData())
app.factory('chartFactory', ['$http', function($http) {
var service = {
height_chart: window.innerHeight * 0.4,
labels: [],
series: ['GDAX Value'],
data: [],
options: {
responsive: true,
maintainAspectRatio: false,
scales: {
yAxes: [{
id: 'y-axis-1',
// type: 'linear',
display: true,
position: 'left',
ticks: {
beginAtZero: false,
callback: function(value, index, values) {
if (parseInt(value) >= 1000) {
return '$' + value.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
} else {
return '$' + value;
}
}
}
}],
xAxes: [{
display: false
}]
}
},
getChartData: function() {
$http.get('/portfolio/get-chart-data')
.then(function(response) {
service.labels = response.data[0]
service.data = response.data[1]
})
}
}
return service
}])
Controller
app.controller('chartCtrl', chartCtrl)
chartCtrl.$inject = ['$scope', '$interval', 'chartFactory']
function chartCtrl($scope, $interval, chartFactory) {
var vmChart = this
vmChart.height_chart = chartFactory.height_chart
vmChart.labels = chartFactory.labels
vmChart.series = chartFactory.series
//this data hasn't loaded yet.
vmChart.data = [chartFactory.data]
vmChart.onClick = function(points, evt) {
console.log(points, evt)
}
vmChart.datasetOverride = [{
yAxisID: 'y-axis-1'
}]
vmChart.options = chartFactory.options
chartFactory.getChartData()
//the chart never shows up on the first view, even after the function loads the data in the factory.
}
<div ng-controller="chartCtrl as vmChart" class="chart-container">
<canvas id="line" class="chart chart-line" chart-data="vmChart.data" chart-labels="vmChart.labels" chart-series="vmChart.series" chart-options="vmChart.options" chart-dataset-override="vmChart.datasetOverride" chart-click="vmChart.onClick" style="width:100%;">
</canvas>
</div>
Just to clarify - the chart does load, but not until I switch to a different view then back again. How do I get the chart to load on. the first view once the data is loaded in the factory?
A http request takes around 200 ms to fetch data but the DOM gets loaded before the request is completed.So the first time when you land on the page ,the chart data gets populated but only after the whole page has been loaded.
Try this:
Make the getChartData function 'async' and add 'await' to http request to tell DOM to wait till the request has been completed.
In Chart Factory :
getChartData: async function() {
await $http.get('/portfolio/get-chart-data')
.then(function(response) {
service.labels = response.data[0]
service.data = response.data[1]
})
}
Please add chartFactory.getChartData() after vm declaration, like below-
app.controller('chartCtrl', chartCtrl)
chartCtrl.$inject = ['$scope', '$interval', 'chartFactory']
function chartCtrl($scope, $interval, chartFactory) {
var vmChart = this
chartFactory.getChartData()
vmChart.height_chart = chartFactory.height_chart
vmChart.labels = chartFactory.labels
vmChart.series = chartFactory.series
//this data hasn't loaded yet.
vmChart.data = [chartFactory.data]
vmChart.onClick = function(points, evt) {
console.log(points, evt)
}
vmChart.datasetOverride = [{
yAxisID: 'y-axis-1'
}]
vmChart.options = chartFactory.options
//the chart never shows up on the first view, even after the function loads the data in the factory.
}
At the moment I am retrieving data from the server.
[
{
id:1,
name:demo,
request: {
id: 1,
localCompany: {
id: 1
}
}
}]
[{ }, { }] so this is how my json object looks.
When I get call the $http service and put it in the gridOptions: {data: this.data}
I get this error in the console window: TypeError: newRawData.forEach is not a function.
data: ng.IPromise<any[]> = this.programService.getRequestsForProgram(this.model.id).then((data: any) => {
console.log(data);
return data;
});
gridOptions: {} = {
data: this.data ,
paginationPageSize: 5
//columnDefs: this.programCountryService.getHeaders()
};
This is the code I am using at the moment.
Any idea how I can get rid of this error? And is it possible that the grid only shows localCompany.Id and not the name:demo?
Try to put the data in $scope.data
Like $scope.data=getdata from server
and then
gridOptions: {} = {
data: $scope.data ,
paginationPageSize: 5
//columnDefs: this.programCountryService.getHeaders()
};
Put data into $scope and than to gridOptions.data = $scope.data.
If you want to show only data for localCompany.id you need to make definition for columnDefs for field request with custom template like:
'<div class="ui-grid-cell-contents">{{ COL_FIELD.id }}</div>'
I'm trying to integrate Angular Bootstrap Calendar to my Laravel 5 project. Right now, the calendar works using the provided pre-populated demo list of events.
vm.events = [
{
title: 'An event',
type: 'warning',
startsAt: moment().startOf('week').subtract(2, 'days').add(8, 'hours').toDate(),
endsAt: moment().startOf('week').add(1, 'week').add(9, 'hours').toDate(),
draggable: true,
resizable: true
}, {
title: 'Event 2',
type: 'info',
startsAt: moment().subtract(1, 'day').toDate(),
endsAt: moment().add(5, 'days').toDate(),
draggable: true,
resizable: true
}, {
title: 'This is a really long event title that occurs on every year',
type: 'important',
startsAt: moment().startOf('day').add(7, 'hours').toDate(),
endsAt: moment().startOf('day').add(19, 'hours').toDate(),
recursOn: 'year',
draggable: true,
resizable: true
}
];
I would like to retrieve and format the events from my database like the example above, but I'm not sure how to tackle this from my controller.
On the Angular Calendar side, I've read that I can use the angular $http service to load the events, like this:
$http.get('/events').success(function(events) {
//TODO - format your array of events to match the format described in the docs
$scope.events = events; //Once formatted correctly add them to the scope variable and the calendar will update
});
Any help would be greatly appreciated
What you would want to do is create a service that takes care of all the HTTP request/response handling and have your controller consume it to get/save/update data. Something like:
// assuming that you have a REST service endpoint at /events
// create your service that will handle all HTTP interaction for the events resource
app.factory('EventsService', ['$http', function($http) {
return {
getAll: function() {
// fetch all events asynchronously
return $http.get('/events').success(function(response) {
var events = response.data;
// if you need to do any pre-processing of the events first, do it here
// pass your events to the next function in the promise chain.
return events;
}, function(err) {
// handle errors here
// pass your error object down the chain in case other error callbacks are added later on to the promise.
return err;
});
}
};
}]);
app.controller('YourController', ['$scope', 'EventsService', function($scope, EventsService) {
// call the asynchronous service method and add your promise success callback that returns your array of events to be bound to your context.
EventsService.getAll().then(function(evts) {
$scope.events = evts;
}, function(err) {
// do any additional error handling here
});
});
Based upon a prior SO article on injecting toastr into your app/controller. I have setup my app.js as follows:
(function () {
app = angular.module("app", ['breeze.angular']).value('ngToastr', toastr);
//added toaster as factory so it can be injected into any controller
angular.module('app').factory('ngNotifier', function (ngToastr) {
return {
notify: function (msg) {
ngToastr.success(msg);
},
notifyError: function (msg) {
ngToastr.error(msg);
},
notifyInfo: function (msg) {
ngToastr.info(msg);
}
}
});
})();
as one of the answers stated I now have access to the toastr control from any controller.
app.controller('reportController', function ($scope, reportLibraryService, ngNotifier, $log) {
//report section
var rvm = this;
rvm.getReportList = GetReportList;
rvm.onError = OnError;
rvm.onReportComplete = OnReportComplete;
$scope.userId = 1;
GetReportList($scope.userId);
function OnReportComplete(response) {
$scope.reportList = response;
ngNotifier.notify("Reports Loaded");
};
function OnError(reason) {
$scope.error = "Could not fetch the data.";
$log.error(reason);
};
function GetReportList(userId) {
$log.info("Getting reports for userid " + userId)
reportLibraryService.getAllReports($scope.userId).then(rvm.onReportComplete, rvm.onError);
};
});
The question I have is how do I override the default options? I have tried two approaches so far. First adding an toastr div within the html with the options set, which did not work. And then I tried adding them within the factory but they were ignored there as well.
angular.module('app').factory('ngNotifier', function (ngToastr) {
return {
notify: function (msg) {
ngToastr.success(msg);
ngToastr.options = {
"closeButton": false,
"debug": false,
"progressBar": false,
"positionClass": "toast-bottom-right",
"onclick": null,
"showDuration": "300",
"hideDuration": "1000",
"timeOut": "5000",
"extendedTimeOut": "1000",
"showEasing": "swing",
"hideEasing": "linear",
"showMethod": "fadeIn",
"hideMethod": "fadeOut"
}
}, ...
As a second part to this is toastr the correct tool to use or should I be using angular-toaster instead since this is an angular app? I currently do not have any jQuery dependencies anywhere else in my application.
thanks for any suggestions
For those trying to override a particular notification, rather than simply override the defaults globally, I was able to do so but with a catch. I wanted to make errors persist (set timeOut to 0) while success messages fade. So for a normal happy-path notification I just use:
toaster.success('Nothing to see here folks', 'Move along');
But for errors I want the message to persist so they can show their manager, write down the error message, whatever. This is easy with the original toastr project, you just pass a JSON object of override options as your last argument such as:
toastr.error('Original toastr example', 'Click to dismiss', {timeOut: 0});
Angularjs-toaster is different, you pass your params to the pop function.
But this did NOT work:
toaster.pop({
type: 'error',
title: 'Need More Information',
body: 'Error 42 occurred, run for the hills!',
timeOut: 0
});
I looked in the toaster.js code (I am using version 0.4.15) and it looks like you can pass ordered parameters to pop instead of a JSON object. This DID work:
toaster.pop(
'error',
'Need More Information',
'Error 42 occurred, run for the hills!',
0 );
Of course I'd prefer to pass an object with named params over a bunch of unlabeled params. I looked at their code closer and saw they changed the case sensitivity from timeOut to timeout!!! This works:
toaster.pop({
type: 'error',
title: 'Need More Information',
body: 'Error 42 occurred, run for the hills!',
timeout: 0
});
Just put toastr options in app.config
app.config(["toastrConfig",function(toastrConfig) {
var options = {
"closeButton": true,
"debug": false,
"newestOnTop": false,
"progressBar": true,
"positionClass": "toast-top-right",
"preventDuplicates": false,
"onclick": null,
"showDuration": "300",
"hideDuration": "1000",
"timeOut": "5000",
"extendedTimeOut": "1000",
"showEasing": "swing",
"hideEasing": "linear",
"showMethod": "fadeIn",
"hideMethod": "fadeOut"
};
angular.extend(toastrConfig, options);
})]);
Since "AngularJS Toaster" is an AngularJS port of the "toastr" jQuery library, it is definitely better to use it in your AngularJS application.
I use it in similar manner, and didn't have problems setting options in HTML template like this:
<toaster-container toaster-options="{'position-class': 'toast-bottom-right', 'close-button': true, 'body-output-type': 'trustedHtml', 'showDuration': '400', 'hideDuration': '200',}"></toaster-container>
If you have a base angular controller, you can add your site-wide angular.options there. Then, if necessary, you can override the options you want in the toastung controller.
toastr.options = {
"closeButton": true,
"debug": false,
"newestOnTop": false,
"progressBar": true,
"positionClass": "toast-top-right",
"preventDuplicates": false,
"onclick": null,
"showDuration": "300",
"hideDuration": "1000",
"timeOut": "5000",
"extendedTimeOut": "1000",
"showEasing": "swing",
"hideEasing": "linear",
"showMethod": "fadeIn",
"hideMethod": "fadeOut"
};
I have created MVC 4.0 app using Web API which returns data in JSON format (I am serializing object to json using NewtonSoft.Json) and trying to bind data in ng-Grid. I am receiving data in following format:
"[{\"Name\":\"FIRST_NAME\",\"Value\":\"FIRST_NAME\"},{\"Name\":\"CURRENT_DATE_TIME\",\"Value\":\"CURRENT_DATE_TIME\"},{\"Name\":\"CLIENTID\",\"Value\":\"CLIENTID\"},{\"Name\":\"CALLMODE\",\"Value\":\"CALLMODE\"}, {\"Name\":\"new 321\",\"Value\":null}]"
When i tried to assign same to data: of ng-Grid, each char populated on different row. following is the javascript i have written:
var guidesRespApp = angular.module('guidesRespApp', ['ngGrid']);
//Get Data from restful API.
guidesRespApp.controller('MyCtrl', function ($scope, $http) {
$http.get('/api/datadictionary').success(function (thisdata) {
$scope.myData = thisdata;
});
$scope.filterOptions = {
filterText: '',
useExternalFilter: true,
};
//Setting grid options
$scope.gridOptions = {
data: 'myData',
multiSelect: true,
filterOptions: { filterText: '', useExternalFilter: false },
enableRowReordering: false,
showGroupPanel: false,
maintainColumnRatios: false,
groups: [],
showSelectionCheckbox: true,
showFooter: true,
enableColumnResize: true,
enableColumnReordering: true
};
// $scope.totalFilteredItemsLength = function() {
// //return self.filteredRows.length;
// };
});
If manually assigned like below, data is getting displayed in grid:
$scope.myData = [{"Name":"FIRST_NAME","Value":"FIRST_NAME"},{"Name":"CURRENT_DATE_TIME","Value":"CURRENT_DATE_TIME"},{"Name":"CLIENTID","Value":"CLIENTID"},{"Name":"CALLMODE","Value":"CALLMODE"}];
can anyone please help me to understand how to fix it?
Also i wanted to display count of filtered items when i key in values in filtertext.
As mentioned on http://angular-ui.github.io/ng-grid/ , Data being displayed in the grid is of type array and each element in that array mapped to a row being displayed. So I modified my code like below and it worked for me:
$http.get('http://localhost:12143/api/datadictionary').success(function (thisdata) {
//Convert data to array.
var myData = $.parseJSON(JSON.parse(thisdata));
$scope.myData = myData;
});
even var myData = $.parseJSON(angular.fromJson(thisdata)); also working. Just we need first to parse the data (for this I used JSON.parse()) and then convert to array (for this i used $.parseJSON()).
Try changing the get callback to one of the following:
$http.get('/api/datadictionary').success(function (thisdata) {
$scope.myData = JSON.parse(thisdata);
// or
$scope.myData = angular.fromJson(thisdata);
});
Reference this with regards to how webapi is returning json. ASP.NET WebAPI: How to control string content returned to client?