In my angular project, I am using datatable where I have row grouping and row callbacks.
datatable options
openPositionDatatableOptions = {
sDom: 'rt<"bottom"p>',
ajax: (data, callback, settings) => {
this.service.getOpenPositions()
.map(data => data.json().data).catch(this.handleError)
.subscribe(jsondata => {
this.openPositionsData = jsondata;
jsondata.forEach(element => {
if (element.side === 'SLD') {
element.openQuantity = '-' + element.openQuantity;
}
element['delta'] = 0;
element['pl'] = 0;
});
if (jsondata) {
callback({
aaData: jsondata
});
}
},
error => {
this.notifiicationAlert('Some Error Occured While Retrieving Positions Data', 'WARNING');
});
},
columns: [
{ data: 'account.brokerId' },
{ data: 'contract.localSymbol' },
{ data: 'openQuantity' },
{ data: 'delta' },
{ data: 'pl' },
{
data: null,
orderable: false,
defaultContent:
'<a class="fa fa-remove" style="color:#8B0000"></a>',
responsivePriority: 2
}
],
//Grouping By Row Logic
"columnDefs": [
{ "visible": false, "targets": 0 }
],
"order": [[0, 'asc']],
"drawCallback": function (settings) {
var api = this.api();
var rows = api.rows({ page: 'current' }).nodes();
var last = null;
api.column(0, { page: 'current' }).data().each(function(group, i) {
if (last !== group) {
$(rows).eq(i).before(
'<tr class="group"><td colspan="5"><div class="row"><div class="col-lg-6" style="text-align:left">' + group + '</div><div class="col-lg-6" style="text-align:right"><button class="datatableGroupingBtn btn btn-default btn-xs fa fa-remove" value='+group+'></button></div></div></td></tr>'
);
last = group;
}
});
// jQuery button click event
$(".datatableGroupingBtn").on('click',(value)=>{
var clickedRow = value.currentTarget.value;
});
},
//Grouping By Row Logic Ends
rowCallback: (row: Node, data: any | Object, index: number) => {
$('a', row).bind('click', () => {
this.service.closePosition(data.id).catch(this.handleError).subscribe(
res => {
if (res.status == 200) {
//TODO Re-implement this using web-socket
if ($.fn.DataTable.isDataTable(this.service.openPositionTableAlias)) {
const table = $(this.service.openPositionTableAlias).DataTable();
if (this.openPositionsData.length > 1) {
$('td', row)
.parents('tr')
.remove();
} else {
table.clear().draw();
}
this.notifiicationAlert('Position Closed Successfully', 'SUCCESS');
}
}
},
(error: Response) => {
this.notifiicationAlert('Some Problem While Closing The Position', 'WARNING');
}
);
});
return row;
}
};
In my datatable options, I have a drawCallback function inside I am grouping the rows. Inside the function, I also have a jquery click event over #datatableGroupingBtn
"drawCallback": function (settings) {
var api = this.api();
var rows = api.rows({ page: 'current' }).nodes();
var last = null;
api.column(0, { page: 'current' }).data().each(function(group, i) {
if (last !== group) {
$(rows).eq(i).before(
'<tr class="group"><td colspan="5"><div class="row"><div class="col-lg-6" style="text-align:left">' + group + '</div><div class="col-lg-6" style="text-align:right"><button class="datatableGroupingBtn btn btn-default btn-xs fa fa-remove" value='+group+'></button></div></div></td></tr>'
);
last = group;
}
});
// jQuery button click event
$(".datatableGroupingBtn").on('click',(value)=>{
var clickedRow = value.currentTarget.value;
});
}
Now my requirement is, I have to access the class level this that is My OrderComponent class object inside the jquery click event binding of #datatableGroupingBtn. I know that this can be done if I use arrow function over the drawCallback but if I use then other required functionalities won't work as you can see that I have used some properties using function() level this inside drawCallback function.
My component
import { NotificationService } from './../shared/utils/notification.service';
import { Global } from 'app/shared/global';
import { endponitConfig } from 'environments/endpoints';
import { Observable } from 'rxjs';
import { Http } from '#angular/http';
import { OrderService } from './order.service';
import { Component, OnInit, OnDestroy, AfterViewInit } from '#angular/core';
import { Router } from '#angular/router';
declare var $: any;
#Component({
selector: 'app-order',
templateUrl: './order.component.html',
styleUrls: ['./order.component.css']
})
export class OrderComponent {
openPositionsData: any;
openOrdersData: any;
openPositionDatatableOptions = {
sDom: 'rt<"bottom"p>',
ajax: (data, callback, settings) => {
this.service.getOpenPositions()
.map(data => data.json().data).catch(this.handleError)
.subscribe(jsondata => {
this.openPositionsData = jsondata;
jsondata.forEach(element => {
if (element.side === 'SLD') {
element.openQuantity = '-' + element.openQuantity;
}
element['delta'] = 0;
element['pl'] = 0;
});
if (jsondata) {
callback({
aaData: jsondata
});
}
},
error => {
this.notifiicationAlert('Some Error Occured While Retrieving Positions Data', 'WARNING');
});
},
columns: [
{ data: 'account.brokerId' },
{ data: 'contract.localSymbol' },
{ data: 'openQuantity' },
{ data: 'delta' },
{ data: 'pl' },
{
data: null,
orderable: false,
defaultContent:
'<a class="fa fa-remove" style="color:#8B0000"></a>',
responsivePriority: 2
}
],
//Grouping By Row Logic
"columnDefs": [
{ "visible": false, "targets": 0 }
],
"order": [[0, 'asc']],
"drawCallback": function (settings) {
var api = this.api();
var rows = api.rows({ page: 'current' }).nodes();
var last = null;
api.column(0, { page: 'current' }).data().each(function(group, i) {
if (last !== group) {
$(rows).eq(i).before(
'<tr class="group"><td colspan="5"><div class="row"><div class="col-lg-6" style="text-align:left">' + group + '</div><div class="col-lg-6" style="text-align:right"><button class="datatableGroupingBtn btn btn-default btn-xs fa fa-remove" value='+group+'></button></div></div></td></tr>'
);
last = group;
}
});
// jQuery button click event
$(".datatableGroupingBtn").on('click',(value)=>{
var clickedRow = value.currentTarget.value;
});
},
//Grouping By Row Logic Ends
rowCallback: (row: Node, data: any | Object, index: number) => {
$('a', row).bind('click', () => {
this.service.closePosition(data.id).catch(this.handleError).subscribe(
res => {
if (res.status == 200) {
//TODO Re-implement this using web-socket
if ($.fn.DataTable.isDataTable(this.service.openPositionTableAlias)) {
const table = $(this.service.openPositionTableAlias).DataTable();
if (this.openPositionsData.length > 1) {
$('td', row)
.parents('tr')
.remove();
} else {
table.clear().draw();
}
this.notifiicationAlert('Position Closed Successfully', 'SUCCESS');
}
}
},
(error: Response) => {
this.notifiicationAlert('Some Problem While Closing The Position', 'WARNING');
}
);
});
return row;
}
};
constructor(private http : Http, private service : OrderService){
this.http.get(Global.serviceUrl).subscribe(response=>{
this.openPositionsData = response.json().data;
})
}
}
Assign your openPositionDatatableOptions in the constructor, after declaring a self variable
openPositionDatatableOptions : any;
constructor()
{
const self = this;
this.openPositionDatatableOptions = {
//....
"drawCallback": function (settings) {
//....
// jQuery button click event
$(".datatableGroupingBtn").on('click',(value)=>{
var clickedRow = value.currentTarget.value;
console.log(self);//<=== self is your class instance
});
},
}
Inside the method your jQuery event binding is, declare a variable like so
let self = this;
now you should be able to use this variable in your jquery click event binding
Related
I'm developing an admin panel with "SCUTUM" admin template with nuxt.js.
When I trying to use datatables component in the template it gives following error in the console. Component is made by template provider. And I used it as the example given by them.
[Vue warn]: Failed to resolve async component: function Datatable() {
return Promise.all(/*! import() */[__webpack_require__.e(0), __webpack_require__.e(1)]).then(__webpack_require__.bind(null, /*! ~/components/datatables/Datatables */ "./components/datatables/Datatables.vue"));
}
Reason: TypeError: Cannot read property 'display' of undefined
What is the reason for this?
Here is my code
<template>
<div id="sc-page-wrapper">
<div id="sc-page-content">
<ScCard class="">
<ScCardHeader seperator>
<div class="uk-flex-middle uk-grid-small uk-grid" data-uk-grid>
<div class="uk-flex-1">
<ScCardTitle>
List of Lecturers
</ScCardTitle>
</div>
<div class="uk-width-auto#s">
<div id="sc-dt-buttons"></div>
</div>
</div>
</ScCardHeader>
<ScCardBody>
<client-only>
<Datatable
id="sc-dt-buttons-table"
ref="buttonsTable"
:data="dtDData"
:options="dtDOptions"
:buttons="true"
#initComplete="dtButtonsInitialized"
/>
</client-only>
</ScCardBody>
</ScCard>
</div>
</div>
</template>
<script>
const rows = require('~/data/pages/datatables.json');
import ScCard from "#/components/card/";
import {ScCardTitle, ScCardBody, ScCardHeader} from "#/components/card"
export default {
name: 'Lecturer',
components: {
Datatable: () => import('~/components/datatables/Datatables'),
ScCard,
ScCardTitle,
ScCardHeader,
ScCardBody
},
data: () => ({
dtDData: JSON.parse(JSON.stringify(rows)),
dtDOptions: {
buttons: [
{
extend: "copyHtml5",
className: "sc-button",
text: 'Copy'
},
{
extend: "csvHtml5",
className: "sc-button",
text: 'CSV '
},
{
extend: "excelHtml5",
className: "sc-button",
text: 'Excel '
},
{
extend: "pdfHtml5",
className: "sc-button sc-button-icon",
text: '<i class="mdi mdi-file-pdf md-color-red-800"></i>'
},
{
extend: "print",
className: "sc-button sc-button-icon",
text: '<i class="mdi mdi-printer"></i>',
title: 'Custom Title',
messageTop: 'Custom message on the top',
messageBottom: 'Custom message on the bottom',
autoPrint: true
}
]
}
}),
mounted () {
this.$nextTick(() => {
})
},
methods: {
dtButtonsInitialized () {
// append buttons to custom container
this.$refs.buttonsTable.$dt.buttons().container().appendTo(document.getElementById('sc-dt-buttons'))
},
}
}
</script>
<style lang="scss">
</style>
Here is the Datatables component
<template>
<div>
<table :id="id" class="uk-table uk-table-striped uk-table-middle" :class="[tableClass]" style="width:100%">
<thead>
<tr>
<th v-for="header in headers" :key="header" class="uk-text-nowrap">
{{ header }}
</th>
</tr>
</thead>
<slot name="footer"></slot>
</table>
</div>
</template>
<script>
import { mapState } from 'vuex'
import { scMq } from '~/assets/js/utils'
require('~/plugins/jquery');
require('datatables.net/js/jquery.dataTables');
require('datatables.net-responsive');
require('datatables.net-select');
require('./dataTables.uikit');
require('./dataTables.responsive.uikit');
export default {
name: 'Datatable',
props: {
data: {
type: Array,
default: () => [],
required: true
},
options: {
type: Object,
default: () => {}
},
id: {
type: String,
required: true
},
buttons: {
type: Boolean,
default: false
},
autoWidth: Boolean,
tableClass: {
type: String,
default: ''
},
customEvents: {
type: Array,
default: () => []
}
},
data: () => ({
$dt: null
}),
computed: {
dtData () {
return JSON.parse(JSON.stringify(this.data))
},
headers () {
let names = [];
Object.keys(this.data[0]).map(k => {
let name = k.replace(/_/g, ' ');
names.push(name.charAt(0).toUpperCase() + name.slice(1))
});
return names
},
columns () {
let columns = [];
Object.keys(this.data[0]).map(k => {
columns.push({
data: k
})
});
return columns;
},
...mapState([
'vxSidebarMainExpanded'
])
},
watch: {
dtData (newVal, oldVal) {
const newLength = newVal.length;
const oldLength = oldVal.length;
const newIds = newVal.map(k => {
return k.id
});
const oldIds = oldVal.map(k => {
return k.id
});
if(newLength > oldLength) {
let uniq = newIds.filter(k => {
return !oldIds.includes(k)
});
if (uniq.length) {
const newEl = newVal.filter(obj => {
return obj.id === uniq[0]
});
this.$dt.row.add(newEl[0]).draw('full-hold');
}
} else {
let uniq = oldIds.filter(k => {
return !newIds.includes(k)
});
if (uniq.length) {
this.$dt.row(':eq('+ uniq[0] +')').remove().draw('full-hold')
}
}
},
vxSidebarMainExpanded () {
if(scMq.mediumMin()) {
setTimeout(() => {
$('#' + this.id).resize()
}, 300);
}
}
},
mounted () {
const self = this;
if(self.buttons) {
const pdfMake = require('~/assets/js/vendor/pdfmake/pdfmake');
const pdfFonts =require('~/assets/js/vendor/pdfmake/vfs_fonts');
pdfMake.vfs = pdfFonts.pdfMake.vfs;
window.JSZip = require("~/assets/js/vendor/jszip");
require('datatables.net-buttons');
require('datatables.net-buttons/js/buttons.html5');
require('datatables.net-buttons/js/buttons.print');
}
let _options = {
data: self.data,
columns: self.columns,
responsive: true,
"initComplete" (settings, json) {
self.$dt = this.api();
self.$emit('initComplete');
}
};
const options = $.extend(_options, self.options);
if(options.responsive === 'responsiveModal') {
_options.responsive = {
details: {
display: $.fn.dataTable.Responsive.display.modal({
header (row) {
return 'Details for row ' + (parseInt(row[0]) + 1);
}
}),
renderer: $.fn.dataTable.Responsive.renderer.tableAll({
tableClass: 'table'
})
}
}
}
$('#' + this.id).DataTable(options);
if(this.customEvents.length) {
this.customEvents.forEach(event => {
this.$dt.on(event.name, event.function)
})
}
}
}
</script>
Is there a way to resolve this?
I've a data table as shown below:
<div class="card-body table-responsive">
<table
class="table display table-striped table-hover table-bordered row-border hover responsive nowrap"
datatable
[dtOptions]="dtOptions"
datatable=""
#dataTable
id="issueTable"
>
<thead class="headColor"></thead>
<tbody style="text-align: center;"></tbody>
</table>
</div>
JS:
import { Component, OnInit, Renderer, AfterViewInit, ViewChild, HostListener } from '#angular/core';
import { Router, RouterLink } from '#angular/router';
import { routerTransition } from '../../router.animations';
import { DataTableDirective } from 'angular-datatables';
import { IssueDataServiceService } from './issue-data-service.service';
import 'datatables.net';
import 'datatables.net-bs4';
window['jQuery'] = window['$'] = $;
#Component({
selector: 'app-charts',
templateUrl: './issues.component.html',
styleUrls: ['./issues.component.scss'],
animations: [routerTransition()]
})
export class IssuesComponent implements OnInit, AfterViewInit {
// viewer = document.getElementById('view');
/**
* gets settings of data tables
*
* #type {DataTables.Settings}
* #memberof IssuesComponent
*/
constructor(public router: Router) { }
#ViewChild(DataTableDirective)
datatableElement: DataTableDirective;
message = '';
title = 'angulardatatables';
#ViewChild('dataTable') table: { nativeElement: any; };
dataTable: any;
dtOptions: DataTables.Settings = {};
// someClickhandler(info: any): void {
// this.message = info.number + '-' + info.assignedto + '-' + info.company;
// console.log(this.message);
// }
ngOnInit(): void {
this.dtOptions = {
pagingType: 'full_numbers',
pageLength: 15,
processing: true,
responsive: true,
autoWidth: false,
dom: 'Bfrtip',
'ajax': {
url: 'http://localhost:8080/incident-updated',
type: 'GET',
dataSrc: 'result',
},
columns: [
{
title: 'Incident',
data: 'number'
},
{
title: 'Product',
data: 'u_product'
},
{
title: 'Status',
data: 'state'
},
{
title: 'Created By',
data: 'sys_created_by'
},
{
title: 'Group',
data: 'assignment_group'
},
{
title: 'Category',
data: 'u_category'
},
{
title: 'Updated on',
data: 'sys_updated_on'
},
{
title: 'Action',
data: null,
// render: function(data, type, full) {
// return '<a class="btn btn-primary btn-sm" style="color: #fff;" id="view" (click)="view($event)">View</a>';
// }
defaultContent: '<button class="btn btn-sm btn-primary viewer"> View </button>'
}
]
};
let table = this.dataTable;
table = $(this.table.nativeElement);
const _curClassRef = this;
$('#issueTable tbody td').unbind();
$('#issueTable tbody td').on('click', function (event: any) {
event.stopPropagation();
// const tr = $(this).closest('tr');
// const row = table.row(tr);
if (this.className = 'viewer') {
_curClassRef.redirect();
}
});
// function view($event: any) {
// event.stopPropagation();
// this.router.navigate(['/event-viewer']);
// }
// $('#viewer').on('click', function() {
// event.stopPropagation();
// this.router.navigate(['/event-viewer']);
// });
// console.log('table is ==>', this.dataTable);
// $('#view tbody').on('click', 'button', function () {
// const data = this.dataTable.row($(this).parents('tr').data);
// alert('Data is ==>' + data);
// });
}
redirect() {
alert('alsjfhksjdf');
}
// #HostListener('click')
// viewer() {
// event.stopPropagation();
// this.router.navigate(['/event-viewer']);
// }
ngAfterViewInit(): void {
// Called after ngAfterContentInit when the component's view has been initialized. Applies to components only.
// Add 'implements AfterViewInit' to the class.
// this.viewer.addEventListener('click', function() {
// event.stopPropagation();
// // this.router.navigate(['/event-viewer']);
// alert('shdfiskludhzj');
// });
}
// viewer() {
// alert('sdjfhsklzdjh');
// }
// viewer(event: any) {
// event.stopPropagation();
// this.router.navigate(['/event-viewer']);
// }
// buttonInRowClick(event: any): void {
// event.stopPropagation();
// console.log('Button in the row clicked.');
// this.router.navigate(['/event-viewer']);
// }
// wholeRowClick(): void {
// console.log('Whole row clicked.');
// }
}
But when I click on button, alert doesn't come, how do I fix it?
You are on ngOnInit so probably Angular didn't have time to render the table when you used JQuery here:
$('#issueTable tbody td').unbind();
$('#issueTable tbody td').on('click', function (event: any) {
event.stopPropagation();
// const tr = $(this).closest('tr');
// const row = table.row(tr);
if (this.className = 'viewer') {
_curClassRef.redirect();
}
});
Try wrapping this code in a setTimeout(()=> { }) like this:
setTimeout(()=> {
$('#issueTable tbody td').unbind();
$('#issueTable tbody td').on('click', function (event: any) {
event.stopPropagation();
// const tr = $(this).closest('tr');
// const row = table.row(tr);
if (this.className = 'viewer') {
_curClassRef.redirect();
}
});
})
By doing this you will force the Change Detection to be executed once, which should cause your table to be rendered. Only at that point Jquery will be able to select your HTML elements
I'm using datatables and I have to select the first row of table.
The problem is select the first row when the table are reload (the table show the rooms of a building, so user can change the building).
This is my code:
function showRoom(idBuilding){
document.getElementById("roomTable").removeAttribute("style");
if ( ! $.fn.DataTable.isDataTable( '#roomTable' ) ) {
roomTable = $('#roomTable').DataTable({
responsive:true,
select: true,
"autoWidth": false,
"language": {
"emptyTable": "No room available!"
},
"ajax":{
"url": "/buildings/"+ idBuilding + "/rooms/",
"data": function ( d ) {
d.idRoomType = idRoomType;
},
"dataSrc": function ( json ) {
if (typeof json.success == 'undefined')
window.location.href = "/500";
else if (json.success){
return json.result.data;
}else{
notifyMessage(json.result, 'error');
return "";
}
},
"error": function (xhr, error, thrown) {
window.location.href = "/500";
}
},
"columns": [
{ "data": "name" },
{ "data": "capacity"},
{data:null, render: function ( data, type, row ) {
var string ="";
for (index = 0; index < data.accessories.length; ++index){
string = string + '<i aria-hidden="true" class="'+ data.accessories[index].icon+'" data-toggle="tooltip" title="'+data.accessories[index].name+'"style="margin-right:7px;" ></i>';
}
return string;
}
},
],
"fnInitComplete": function(oSettings, json) {
if (roomTable.rows().any()){
roomTable.row(':eq(0)').select();
selectedRoom(0);
}
initializeCalendar();
}
});
}
else {
roomTable.ajax.url("/buildings/"+ idBuilding + "/rooms/?idRoomType=" + idRoomType).load(selectFirstRow());
}
roomTable.off('select')
.on( 'select', function ( e, dt, type, indexes ) {
selectedRoom(indexes);
} );
roomTable.off('deselect').on( 'deselect', function ( e, dt, type, indexes ) {
reservationForm.room = -1;
$('#calendar').fullCalendar('option', 'selectable', false);
$("#calendar").fullCalendar("refetchEvents");
} );
}
function selectFirstRow(){
if (roomTable.rows().any()){
roomTable.row(':eq(0)').select();
selectedRoom(0);
}
initializeCalendar();
}
function selectedRoom(index){
var room = roomTable.rows( index ).data().toArray()[0];
reservationForm.room = room.idRoom;
$('#calendar').fullCalendar('option', 'minTime', room.startTime);
$('#calendar').fullCalendar('option', 'maxTime', room.endTime);
$('#calendar').fullCalendar('option', 'selectable', true);
$("#calendar").fullCalendar("refetchEvents");
}
On the first load all work fine, but when
roomTable.ajax.url("/buildings/"+ idBuilding + "/rooms/?idRoomType=" + idRoomType).load(selectFirstRow());
is called it seems to select the row before reload the table, so I have no row select (keep select the row of first load but now it is not visible).
Do you have idea how can I select on the load after?
UPDATE: the temporary solution is to use destroy: true but I would like a better solution like this:
if ( ! $.fn.DataTable.isDataTable( '#roomTable' ) ) {
roomTable = $('#roomTable').DataTable({
destroy: true, //it is useful because with standard code I have problem with first row selection, now it create the table each time
responsive:true,
select: true,
"autoWidth": false,
"language": {
"emptyTable": "No room available!"
},
"ajax":{
"url": "/buildings/"+ building.idBuilding + "/rooms/",
"data": function ( d ) {
d.idRoomType = idRoomType;
},
"dataSrc": function ( json ) {
if (typeof json.success == 'undefined')
window.location.href = "/500";
else if (json.success){
return json.result.data;
}else{
notifyMessage(json.result, 'error');
return "";
}
},
"error": function (xhr, error, thrown) {
window.location.href = "/500";
}
},
"fnDrawCallback": function(oSettings) {
if (roomTable.rows().any()){
roomTable.row(':eq(0)').select();
selectedRoom(0);
}
},
"fnInitComplete": function() {
initializeCalendar();
},
"columns": [
{ "data": "name" },
{ "data": "capacity"},
{data:null, render: function ( data, type, row ) {
var string ="";
for (index = 0; index < data.accessories.length; ++index){
string = string + '<i aria-hidden="true" class="'+ data.accessories[index].icon+'" data-toggle="tooltip" title="'+data.accessories[index].name+'"style="margin-right:7px;" ></i>';
}
return string;
}
},
],
});
}
else {
roomTable.ajax.url("/buildings/"+ idBuilding + "/rooms/?idRoomType=" + idRoomType).load(selectFirstRow());
}
But fnDrawCallback is called before ajax so I don't have the value, datatables keep on loading...
The fnInitComplete callback is called only when the datatable is initialized, so only once. You can use the fnDrawCallback, which is called every time the datatables redraws itself.
Just change fnInitComplete to fnDrawCallback. More about datatable callbacks (legacy version) here.
I have a table that contains a button that activates/deactivates users. When I click that button it makes a API call to change the status of the user. What I am having trouble with is performing a live update with the view after the API call. Currently, the only way I see the text switch is when I refresh the page.
Here is my Admin.html where the text on the button should switch between 'Active' and 'Inactive' when the button is clicked.
<tr ng-repeat="account in $ctrl.account">
<td>{{account.FirstName}}</td>
<td>{{account.LastName}}</td>
<td class="text-center">
<button class="btn btn-sm btn-active-status" ng-class="account.Active === true ? 'btn-info' : 'btn-danger'" ng-bind="account.Active === true ? 'Active' : 'Inactive'" ng-click="$ctrl.UpdateActiveStatus(account.Id, account.Active)"></button>
</td>
</tr>
Here is my AdminController.js
app.component('admin', {
templateUrl: 'Content/app/components/admin/Admin.html',
controller: AdminController,
bindings: {
accounts: '='
}
})
function AdminController(AccountService) {
this.$onInit = function () {
this.account = this.accounts;
}
this.UpdateActiveStatus = function (id, status) {
var data = {
Id: id,
Active: !status
};
AccountService.UpdateActiveStatus(data).then(function (response) {
AccountService.GetAccounts().then(function (data) {
this.account = data;
});
});
};
}
Here is the fix to my problem. Please let me know if there is a better way than this.
function AdminController(AccountService) {
var controller = this;
this.$onInit = function () {
controller.account = this.accounts;
}
this.UpdateActiveStatus = function (id, status) {
var data = {
Id: id,
Active: !status
};
AccountService.UpdateActiveStatus(data).then(function (data) {
for (var i = 0; i < controller.account.length; i++) {
if (controller.account[i].Id === data.Id) {
controller.account[i].Active = data.Active;
}
}
});
};
}
I have tried to reload the data populated by an ajax call but I cant get it to work, it shows the old data even after using the reload method. The thing is that if I change some variables to populate a different data and try to call the following code without refreshing the page it does not reload the updated data =/ Here is my code:
function populateDataGrid() {
$.ajaxSetup({async: false});
var gridinfo="";
$.post("lib/function.php",{activity: activity, shift: shift, date: date},
function (output){
gridinfo = JSON.parse(output);
});
$.ajaxSetup({async: true});
// INITIALIZING THE DATAGRID
var dataSource = new StaticDataSource({
columns: [
{
property: 'id',
label: '#',
sortable: true
},
{
property: 'date',
label: 'date',
sortable: true
},
....
],
formatter: function (items) {
var c=1;
$.each(items, function (index, item) {
item.select = '<input type="button" id="select'+c+'" class="select btn" value="select" onclick="">';
c=c+1;
});
},
data: gridinfo,
delay:300
});
$('#grid').datagrid({
dataSource: dataSource
});
$('#grid').datagrid('reload');
$('#modal-fast-appointment-results').modal({show:true});
}
I found a solution... I had to create a new DataSource (lets call it "AjaxDataSource") and add the ajax request functionality within the data constructor:
(function (root, factory) {
if (typeof define === 'function' && define.amd) {
define(['underscore'], factory);
} else {
root.AjaxDataSource = factory();
}
}(this, function () {
var AjaxDataSource = function (options) {
this._formatter = options.formatter;
this._columns = options.columns;
this._delay = options.delay || 0;
this._data = options.data;
};
AjaxDataSource.prototype = {
columns: function () {
return this._columns;
},
data: function (options, callback) {
var self = this;
setTimeout(function () {
var data;
$.ajax({
url: 'getdata.php',
type: 'POST',
data: 'param1:param1,param2,param2,...,paramN:paramN', // this is optional in case you have to send some params to getdata.php
dataType: 'json',
async: false,
success: function(result) {
data = result;
},
error: function(data){
//in case we want to debug and catch any possible error
// console.log(data);
}
});
// SEARCHING
if (options.search) {
data = _.filter(data, function (item) {
var match = false;
_.each(item, function (prop) {
if (_.isString(prop) || _.isFinite(prop)) {
if (prop.toString().toLowerCase().indexOf(options.search.toLowerCase()) !== -1) match = true;
}
});
return match;
});
}
var count = data.length;
// SORTING
if (options.sortProperty) {
data = _.sortBy(data, options.sortProperty);
if (options.sortDirection === 'desc') data.reverse();
}
// PAGING
var startIndex = options.pageIndex * options.pageSize;
var endIndex = startIndex + options.pageSize;
var end = (endIndex > count) ? count : endIndex;
var pages = Math.ceil(count / options.pageSize);
var page = options.pageIndex + 1;
var start = startIndex + 1;
data = data.slice(startIndex, endIndex);
if (self._formatter) self._formatter(data);
callback({ data: data, start: start, end: end, count: count, pages: pages, page: page });
}, this._delay)
}
};
return AjaxDataSource;
}));
After defining the new DataSource, we just need to create it and call the datagrid as usual:
function populateDataGrid(){
// INITIALIZING THE DATAGRID
var dataSource = new AjaxDataSource({
columns: [
{
property: 'id',
label: '#',
sortable: true
},
{
property: 'date',
label: 'date',
sortable: true
},
....
],
formatter: function (items) { // in case we want to add customized items, for example a button
var c=1;
$.each(items, function (index, item) {
item.select = '<input type="button" id="select'+c+'" class="select btn" value="select" onclick="">';
c=c+1;
});
},
delay:300
});
$('#grid').datagrid({
dataSource: dataSource
});
$('#grid').datagrid('reload');
$('#modal-results').modal({show:true});
}
So now we have our datagrid with data populated via ajax request with the ability to reload the data without refreshing the page.
Hope it helps someone!