jQuery DataTables recreation on data update with socket.io - angularjs

I'm using jQuery DataTables with socket.io on AngularJS, and I'm pushing an item to the data binding list on a socket message and digesting afterwards. When it happened, the datatable recreated itself instead of just updating the data and not working properly. I'm also randomly get the error *Warning: Cannot reinitialise DataTable, and when I do, the datatable failed to display.
JavaScript
var app = angular.module('App', ['ui.bootstrap','ngAnimate', 'datatables']);
app.factory('socket', function () {
var socket = io.connect('http://' + document.domain + ':' + location.port + '/t');
return socket;
});
app.controller('controller', function ($scope, socket, $timeout, DTOptionsBuilder, DTColumnBuilder) {
$scope.data=[];
$scope.headers = {'Name':'name','Title','title'}
socket.on('data', function (d) {
d = angular.fromJson(d);
$scope.data.push(d);
$scope.$digest();
});
$scope.dtOptions = DTOptionsBuilder.newOptions().withPaginationType('full_numbers').withOption('bInfo', false);
$scope.dtColumns = [];
$scope.dtInstance = {};
for (key in $scope.headers) {
$scope.dtColumns.push(DTColumnBuilder.newColumn($scope.headers[key]).withTitle(key));
}
});
HTML
<table id="tbl" datatable="ng" dt-options="dtOptions" dt-columns="dtColumns" dt-instance="dtInstance"
class="table table-striped row-border hover">
<tr class="fade" ng-model="d"
ng-repeat="d in data">

You miss a colon in the headers' literal:
$scope.headers = {'Name':'name','Title' : 'title'}
^
Hopefully the JSON items pushed into data is valid and the full markup is:
<table id="tbl" datatable="ng" dt-options="dtOptions" dt-columns="dtColumns" dt-instance="dtInstance" class="table table-striped row-border hover">
<thead></thead>
<tbody>
<tr class="fade" ng-model="d" ng-repeat="d in data">
<td>{{ d.name }}</td>
<td>{{ d.title }}</td>
</tr>
</tbody>
</table>
Use rerender() instead of §digest (why §digest in the first place?):
socket.on('data', function (d) {
d = angular.fromJson(d);
$scope.data.push(d);
$scope.dtInstance.rerender();
});

Related

I just want to load a particular div on some actions in angular js

I just want to load a particular div on some actions in angular js.
<div class="row">
<div class="col-md-12">
<div id = "div_1" class="table-responsive" ng-controller="usercontroller" ng-init="displayData() ">
<table class="table table-hover table-bordered">
<thead align="center">
<tr>
<th>Service Request Number</th>
<th>Name of service request</th>
<th>Date of request</th>
<th>Closure date</th>
<th>Current state</th>
<th>Current owner</th>
<th>Link to share point folder</th>
<th>Schedule variance</th>
<th align="center">Details</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="x in service track by $index">
<td><span ng-bind="x.id"></span></td>
<td><span ng-bind="x.sales_force_id"></span></td>
<td><span ng-bind="x.submission_date"></span></td>
<td><span ng-bind="x.closure_deadline"></span></td>
<td><span ng-bind="x.item_status"></span></td>
<td></td>
<td></td>
<td></td>
$scope.displayData = function()
{
alert($scope.firstRole);
alert("nishant singh");
if(empIVal == 1 && $scope.firstRole == 'Initiator' ){
alert("i am a initiator");
$http.get("commonGet.jsp?sqlStr=select * from service_request.service_request_data where emp_id="+empHidVal+ " order by id desc")
.then(function(response){
$scope.service = response.data;
});
}
Here I want to load the div again when the displayFunction() is called and response is been returned. Also, the response is JSON object. I am able to call the function using ng-change directive and also able to get the desired JSON object, but I don't know how to load the div again after the response.
wrap your assignment to service variable in timeout so that angular is aware of the changes
$timeout(function(){
$scope.service = response.data;
});
Thus your whole method becomes something like this.
$http.get("commonGet.jsp?sqlStr=select * from service_request.service_request_data where emp_id="+empHidVal+ " order by id desc")
.then(function(response){
$timeout(function(){
$scope.service = response.data;
});
});
}

AngularJS - DOM not updated in Chrome and Mozilla

I'm using angularjs and angular-ui-bootstrap to make a table and page some data, which I get from an API.
I've made sure my service receives the correct data and that the requests are built properly. My pageChange function is properly triggered and my first page gets loaded successfully.
So I have the following controller setup:
(function () {
'use strict';
initContacts.$inject = ['$scope', '$http'];
angular.module('app')
.config(function ($locationProvider) {
$locationProvider.html5Mode(true);
});
angular.module('app', ['ui.bootstrap']).controller('contactSearchController', initContacts);
function initContacts($scope, $http) {
$scope.contacts = [];
$scope.totalItems = 0;
$scope.pages = 0;
$scope.currentPage = 0;
$scope.maxPageLinksShown = 5;
if (window.location.hash !== '') {
$scope.currentPage = window.location.hash.replace('#', '');
}
$http.get("/api/ContactApi/GetPage?pageIndex=" + ($scope.currentPage - 1)).success(function (data) {
$scope.contacts = data.Contacts;
$scope.totalItems = data.Count;
$scope.PageSize = data.Contacts.length;
$scope.pages = Math.ceil((data.Count / $scope.PageSize));
});
$scope.pageChanged = function () {
$http.get("/api/ContactApi/GetPage?pageIndex=" + ($scope.currentPage - 1))
.success(function (data) {
$scope.contacts = data.Contacts;
});
};
}
}
})();
And in my view I have:
<div ng-app="app" ng-controller="contactSearchController">
<table class="table table-striped table-hover contact-search-table">
<thead>
<tr>
<td class="contact-title">
Titel
</td>
<td class="department">
Afdeling
</td>
<td class="name">
Navn
</td>
<td class="work-phone">
Telefon
</td>
<td class="mobile">
Mobile
</td>
<td class="email">
Email
</td>
</tr>
</thead>
<tbody>
<tr ng-repeat="(key, value) in contacts">
<td class="contact-title">{{value.Title}}</td>
<td class="department">{{value.Department}}</td>
<td class="name">{{value.FullName}}</td>
<td class="work-phone">{{value.WorkPhone}}</td>
<td class="mobile">{{value.WorkMobile}}</td>
<td class="email">{{value.Email}}</td>
</tr>
</tbody>
</table>
<div class="col-xs-12 pager-container">
<ul uib-pagination total-items="totalItems" ng-model="currentPage" ng-change="pageChanged()" max-size="maxPageLinksShown" class="pagination-sm" boundary-links="true" num-pages="pages"></ul>
</div>
Now this works to some extent.
My problem
When I click the page links, the pageChanged() function is called, I get the data from my api and it's all correct, the list in the scope appears to be updated fine, but the table in my view doesn't change.
This solution works fine ONLY in IE ! (who would have thought huh...)
No exceptions get thrown.
I swear this was working yesterday.
Any help is much appreciated!
EDIT
What I've tried:
-Putting the assignment of the contacts in an $apply like so:
$scope.pageChanged = function () {
$http.get("/api/ContactApi/GetPage?pageIndex=" + ($scope.currentPage - 1))
.success(function (data) {
$scope.$apply(function () { // apply
$scope.contacts = data.Contacts;
});
});
};
I got a "$digest already in progress" error from this.
tried to wrap the apply in a timeout like so:
$timeout(function(){ //any code in here will automatically have an apply run afterwards });
Got rid of the error but the DOM still won't update.
I had such a problem and I solved it using $scope.$apply:
$scope.pageChanged = function () {
$http.get("/api/ContactApi/GetPage?pageIndex=" + ($scope.currentPage - 1))
.success(function (data) {
$scope.$apply(function () { // apply
$scope.contacts = data.Contacts;
});
});
};
You should use $scope.$applyAsync instead. It will be applied to the next digest cycle.
If you need to target all the $scopes of your AngularJS application, use $rootScope.$applyAsync instead.
Official doc
Okay so what worked in this situation was changing the way I'm visualizing the ng-repeat like so:
<tr ng-repeat="contact in getContacts()">
<td class="contact-title">{{contact.Title}}</td>
<td class="department">{{contact.Department}}</td>
<td class="name">{{contact.FullName}}</td>
<td class="work-phone">{{contact.WorkPhone}}</td>
<td class="mobile">{{contact.WorkMobile}}</td>
<td class="email">{{contact.Email}}</td>
</tr>
And heres the getContacts() function:
$scope.getContacts = function () {
var data = $scope.contacts;
if (data instanceof Array) {
return data;
} else {
return [data];
}
}
I don't really know why that works, but it does.

Using ng-repeat directive on a <tr> element

I use Rails for backend and angularjs for frontend.
In my angularjs controller I have:
app.controller('ReportsInsurerPaymentsCtrl', ['$scope', '$http', function($scope, $http) {
$scope.insurerPayments = [];
$scope.commissions = [];
$scope.insurers = [];
$scope.getInsurerPayments = function () {
$http.get('/reports/insurer_payments.json').success(function (data) {
$scope.insurerPayments = data.payments;
$scope.commissions = data.commissions;
$scope.insurers = data.insurers
})
};
$scope.getInsurerPayments();
}]);
My Rails controller gives me json with 3 arrays: insurerPayments, commissions and insurers. In my view I want to show my insurers, commissions and insurerPayments in a table, so I do something like this:
<table class="table table-bordered table-hover">
<tr>
<th>Insurers</th>
<th>Commissions</th>
<th>Insurer Payments</th>
</tr>
<tr ng-repeat="insurer in insurers">
<td>{{insurer.name}}</td>
<td>{{}}</td>
<td>{{}}</td>
</tr>
</table>
So, how can I do that, using ng-repeat for different arrays? Thank ahead.
use $index for comparsion
<tr ng-repeat="insurer in insurers">
<td>{{insurer.name}}</td>
<td>{{ commissions[$index] }}</td>
<td>{{ insurerPayments[$index] }}</td>
</tr>

What is the proper way to use filters?

I get an issue using $filter('filter') of AngularJS. It seems not working when I have an empty cell in the line...
When a cell is empty on a line if I add a filter it works but when removing the filter the line with the empty cell is deleted from contacts...
AngularJS script :
app.controller("ContactNgController", function($scope, $http, $filter, $document) {
$http.get('/api/mes-contacts').success(function(data, status, headers, config) {
$scope.contacts = data.contacts;
$scope.filteredContacts = data.contacts;
$scope.nbContacts = data.contacts.length;
$scope.limit = data.limit;
$scope.onChange = function(){
$scope.contacts = data.contacts;
$scope.filteredContacts = $filter('filter')($scope.contacts, $scope.search);
};
});
});
Table HTML :
<table class="table table-striped table-hover table-bordered">
<thead>
<tr>
<th>Prénom<input type="text" ng-model="search.firstname" placeholder="Recherche par prénom" ng-change="onChange()" autocomplete="off"></th>
<th>Nom<input type="text" ng-model="search.lastname" placeholder="Recherche par nom" ng-change="onChange()" autocomplete="off"></th>
</tr>
</thead>
<tbody>
<tr ng-repeat="contact in contacts | filter:search | limitTo:limit">
<td>{{contact.firstname}}</td>
<td>{{contact.lastname}}</td>
</tr>
</tbody>
</table>
(source: zupimages.net)

bootstrap-table not rendering upon updating model in Angular

Hi I am not able to render table using bootstrap-table and angular. here is my code, I think I need to call bootstrap-table init method in angular ajax call. Can some one guide me on how to do this..?
angular
.module('reports')
.controller(
'ReportCtrl',
[
'$scope',
'$http',
'ngProgress',
function($scope, $http, ngProgress) {
var vm = this;
vm.mdp = {};
vm.mdp.data = [];
vm.mdp.columns = [];
$scope.submit = function() {
var report = $scope.tab;
$http.post('/reports/cmd/getData', {
report : report,
date : createdAfter
}).success(function(data) {
vm.mdp.data = data;
$.each(data[0], function(key, value){
vm.mdp.columns.push(key);
});
}).error(function(error) {
alert(error);
});
};
} ]);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.15/angular.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div id="mdp" class="panel" ng-controller="ReportCtrl as report" ng-show="panel.isSelected('mdp')">
<table data-toggle="table" data-show-columns="true" data-search="true" data-show-export="true" data-pagination="true" data-height="299">
<thead>
<tr>
<th ng-repeat="c in report.mdp.columns" data-field= {{c}} >{{ c }}</th>
</tr>
</thead>
<tr ng-repeat="r in report.mdp.data">
<td ng-repeat="c in report.mdp.columns">{{ r[c] }}</td>
</tr>
</table>
</div>
Integrating Bootstrap Table with Angular is solved here:
https://github.com/wenzhixin/bootstrap-table/issues/165
https://github.com/AkramKamal/bootstrap-table-examples/tree/master/integrate
I have some minor changes in my implementation of this solution which I will upload to Github / JSFiddle shortly. But the links above will allow you to get going.

Resources