Smart-table clearing table rows and headers when I close a modal? - javascript

I'm using Angular-Smart-table to generate a table full of events for a project.
Adding and removing columns is a requirement, and we have a separate UI component for doing so. This UI component is a modal, and it's a checkbox of the columns I want to include. When this modal closes however, my smart-table goes blank and doesn't update with new choices when I update the table column headers.
Here is the code in the controller that handles the tablesettings event.
function activate(){
vm.$on('tablesettings', function(event, args){
setTimeout(function(){
console.log(args);
vm.tableColumns = {};
angular.forEach(args.columns, function(v,k){
vm.tableColumns[v.value] = v.label;
});
vm.tableRows = [];
addTabletoScope(TableService.cache.data);
},30000)
});
}
function addTabletoScope(td){
vm.tableRows = [].concat(vm.tableData);
console.log(vm.tableColumns);
}
Here is the HTML for the table:
<div class="gTable" style="overflow-x:auto; height:100%;">
<table style="width: 100%" st-table="tableRows" st-safe-src="tableData" st-pipe="tableControl.getPages()" st-pagination-scroll class="table table-striped scroll">
<thead>
<tr>
<th ng-repeat="(key, val) in tableColumns">{{val}}</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="row in tableRows">
<td >{{row.eventDateString}}</td>
<td >{{row.cocom}}</td>
<td >{{row.country}}</td>
<td >{{row.province}}</td>
<td >{{row.district}}</td>
<td >{{row.iedType}}</td>
<td >{{row.incidentType}}</td>
<td>{{row.eventId}}</td>
<!-- <td ng-hide="cityremove">{{row.city}}</td>-->
</tr>
</tbody>
<tfoot>
<tr>
<td colspan="4" class="text-center">
<div st-pagination="" st-items-by-page="pageNumbers" st-displayed-pages="7"></div>
</td>
</tr>
</tfoot>
</table>
</div>
Here's where I broadcast the tablesettings event,
function handleWidgetSettingsReturn(response) {
switch (response.widgetType) {
case "chart": {
if (!angular.isUndefined(response.widgetSubType) &&
response.widgetSubType !== scope.item.settings.widgetSubType) {
scope.item.settings.widgetSubType = response.widgetSubType;
}
break;
}
case "table": {
if (!angular.isUndefined(response.widgetOptions)) {
$log.info("Table settings set");
scope.item.settings.widgetOptions = response.widgetOptions;
console.log(scope.item.settings.widgetOptions);
scope.$broadcast('tablesettings', scope.item.settings.widgetOptions);
}
}
}
}
This is where the modal instance is closed on ok.
function ok() {
var result = {
widgetType: $scope.widgetConfig.widgetType,
widgetSubType: ($scope.widgetConfig.getWidgetSubtype())? $scope.widgetConfig.getWidgetSubtype() : undefined,
widgetOptions: ($scope.widgetConfig.generateWidgetOptions())? $scope.widgetConfig.generateWidgetOptions() : undefined
};
$modalInstance.close(result);
It feels like my template doesn't come back and isn't refreshing or changing, even when I update the scope.tableColumns with the modal response. $scope.apply() also does not work for me, nor a refresh method.
I'm not sure why my smart-table goes blank when I hit ok for that modal.

Related

Angular , How to hide a table row on click of a button

I have a table in which each row has a delete button. on click of the button the data gets deleted. However to verify that record is deleted, I have to refresh the page. I want to hide the current row on click of the delete button. Here is my code.
<table>
<tr>
<th>Delete</th>
<th>Id</th>
<th>Name</th>
</tr>
<tr *ngFor="let person of people" *ngIf="!hideRow">
<td><button (click)="delete(person.id)" title="Delete">Delete</button></td>
<td>person.Id</td>
<td>person.Name</td>
</tr>
</table>
and in my component.ts On delete I change the value of hideRow
delete(id) {
this.hideTr = true;
this.personService.delete(id).subscribe(p=> console.log(p));
}
hideRow is a boolean variable with default value of false. The problem is that when I click on delete, all the rows become hidden(of course). How can I refer just to the current row?
When you want to delete the row then you should delete it in actual instead of hide row. No need of *ngIf="!hideRow". You no need to refresh the page, this is beauty of AngularJS. Below is code to delete particular row. Pass $index of the row:
HTML code:
<table>
<tr>
<th>Delete</th>
<th>Id</th>
<th>Name</th>
</tr>
<tr *ngFor="let person of people">
<td><button (click)="delete($index)" title="Delete">Delete</button></td>
<td>person.Id</td>
<td>person.Name</td>
</tr>
</table>
JavaScript Code:
// delete row
$scope.delete = function(index) {
$scope.people.splice(index, 1);
};
Simple yet more effective :
Template Side :
<tr *ngFor="let person of people" *ngIf="!person?.hideRow">
<td><button (click)="delete(person)" title="Delete">Delete</button></td>
<td>person.Id</td>
<td>person.Name</td>
</tr>
Component Side :
delete(person) {
person.hideRow = true;
this.personService.delete(person.id).subscribe(p=> console.log(p));
}
Without changing user's (property) interface
Template Side :
<tr *ngFor="let person of people;let i = index;">
<td><button (click)="delete(i , person.id)" title="Delete">Delete</button></td>
<td>person.Id</td>
<td>person.Name</td>
</tr>
Component Side :
delete(index , id) {
this.people.splice(index, 1);
this.personService.delete(id).subscribe(p=> console.log(p));
}
Based from the code you provided, I would remove this part *ngIf="!hideRow" and add this to your component
delete(id) {
this.personService.delete(id).subscribe(p=> {
console.log(p);
this.people.filter( person => person.id !== id)
// or you can use splice by using the index
});
}
Now your html is simpler and no need to use *ngIf
<table>
<tr>
<th>Delete</th>
<th>Id</th>
<th>Name</th>
</tr>
<tr *ngFor="let person of people">
<td><button (click)="delete(person.id)" title="Delete">Delete</button></td>
<td>person.Id</td>
<td>person.Name</td>
</tr>
</table>

How to iterate over filtered rows in Angular datatable

Lets say, I have simple datatable
<table datatable="" dt-options="dtOptions" dt-column-defs="dtColumnDefs" class="row-border hover">
<thead>
<th>ID</th>
<th>Name</th>
</thead>
<tbody>
<tr ng-repeat"reservation in reservations">
<td>{{reservation.ID}}</td><td>{{reservation.name}}</td>
</tr>
</tbody>
</table>
When I put some string into search box datatable is being filtered. Now I want to iterate in Angular over filtered rows and read IDs to array. How to deal with it in Angular? I can use jquery but I do not want make a mess in code.
$scope.addressDTInstance = {};
var j = $scope.addressDTInstance.DataTable.rows();
<table id="addressSelectionTable" class="table table-condensed table-bordered" datatable="ng" dt-options="addressdtOptions" dt-column-defs="addressdtColumnDefs" dt-instance="addressDTInstance">
This is something to get you on your way. Need an instance of dtInstance which you don't have. So add dt-instance='dtInstance' in the html table tag.
Then initiate it at the top of your controller, $scope.dtInstance = {};.
Perform a click or some action in your javascript that you can set a break point on and then examine your $scope.dtInstance to see what all properties and methods you have. As you see in my snippet I'm accessing DataTable.Rows of my dtInstance. If you need better example or help let leave me a comment and I'll revise.
UPDATE
Here is a method I found that works. I am ofcourse using the DTOptionsbuilder. This will get called twice, first when it is created and second when i populated the array variable that is populating my table. I just check to see if rows exist and that the first one isn't 'No results'.
$scope.addressdtOptions = DTOptionsBuilder.newOptions()
.withOption('bFilter', false)
.withOption('bInfo', false)
.withOption('paging', false)
.withOption('processing', true)
.withOption('aaSorting', [1, 'asc'])
.withOption('language', { zeroRecords: 'No results' })
.withOption('initComplete', function () {
var rows = $("#addressSelectionTable > tbody > tr");
if (rows.length > 0 && rows[0].innerText !== "No results") {
var x = 3;
}
});
Here i am setting that variable that is ng-repeat for table. You may not be doing it my way, but you should be able to figure it out for your way.
$.when($OfficerService.GetAddressSelections($scope.officer.EntityID, $scope.officer.EntityTypeID, $scope.officer.MemberID)).then(function (result) {
$scope.addresses = result.data;
$scope.$applyAsync();
});
<table id="addressSelectionTable" class="table table-condensed table-bordered" datatable="ng" dt-options="addressdtOptions" dt-column-defs="addressdtColumnDefs" dt-instance="addressDTInstance">
<thead>
<tr>
<th></th>
<th>Type</th>
<th>Address</th>
<th>City</th>
<th>State</th>
<th>Zip</th>
<th>Country</th>
<th></th>
</tr>
</thead>
<tbody>
<tr ng-repeat="a in addresses">
<td class="centerColumn">
<input type="button" class="btn btn-primary" value="Select" ng-click="selectAddress(a.AddressID,a.AddressLocationCode,$event)" />
</td>
<td>
<span ng-if="a.AddressLocationCode == 'E'">Office</span>
<span ng-if="a.AddressLocationCode == 'M'">Member</span>
</td>
<td>
{{a.AddressLine1}}
<span ng-if="a.AddressLine2 != null"><br /> {{a.AddressLine2}}</span>
</td>
<td>{{a.City}}</td>
<td>{{a.StateCode}}</td>
<td>{{a.Zip}}</td>
<td>{{a.CountryCode}}</td>
<td>{{a.AddressID}}</td>
</tr>
</tbody>
</table>
For me it works: $scope.dtInstance.DataTable.rows( { search: 'applied' } ).data()

How can i make some of the table rows not selectable in SmartTable angularjs

I am using angularJS and smart table framework to manage my table in html:
The table rows are selectable using SmartTable attribute : st-select-row="row".
after user selects rows and click "add" button the selected data registered to some other list.
I don't want to remove added rows from table but I do want them to be not selectable.
This is code example:
HTML:
<body ng-app="FarmManagment" ng-controller="mainCtrl">
<table id="Table" class="table table-hover" st-table="displayedCollection" st-safe-src="rowCollection">
<thead>
<tr>
<th st-sort="farmName">Farm Name</th>
<th st-sort="FarmDescription">Description</th>
<th st-sort="DataCenter">DC</th>
</tr>
</thead>
<tbody>
<tr st-select-row="row" st-select-mode="multiple" ng-repeat="row in displayedCollection">
<td ng-bind="row.farmName">{{row.farmName}}</td>
<td ng-bind="row.FarmDescription"></td>
<td ng-bind="row.DataCenter"></td>
</tr>
</tbody>
</table>
<button id="add" ng-click="add(displayedCollection)"> add </button>
<li>
<ul ng-bind="row.farmName" ng-repeat="row in added"></ul>
</li>
</body>
JavaScript:
var app = angular.module('FarmManagment', ['smart-table']);
app.controller('mainCtrl', function ($scope) {
$scope.rowCollection = [
{farmName: 'farm1', FarmDescription: 'some farm1', DataCenter: 'London'},
{farmName: 'farm2', FarmDescription: 'some farm2', DataCenter: 'Paris'},
{farmName: 'farm3', FarmDescription: 'some farm3', DataCenter: 'Berlin'}
];
$scope.added = [];
$scope.add = function(rows){
angular.forEach(rows,function(row){
if (row.isSelected === true){
row.isSelected = false;
var index = $scope.added.indexOf(row);
if(index === -1){
$scope.added.push(row);
// row.disableSelection this is what i want to do
}
}
});
};
});
How can I implement such behavior?
plunker code:plunker
Thanks
Dima
You can add condition like
<tr st-select-row="isSelectableRow(row)" st-select-mode="multiple" ng-repeat="row in displayedCollection">
and in the controller
$scope.isSelectableRow = function (row) {
if (~$scope.added.indexOf(row))
return false;
return row;
}
And also, you have incorrect html
<li><ul>..</ul></li>
change it to
<ul><li>..</li></ul>
Working example here
can be done using the attribute st-select-row:
for example prevent the second row to be selectable
<tr st-select-row="$index != 1 ? row : null" st-select-mode="multiple" ng-repeat="row in displayedCollection">
plunker

nested ng-repeat with open particular index with respect to repeated data

Every time the toggle is clicked, all payments are getting replaced with new payments. My problem is how to maintain the payments of a particular index of every click and show at respective index. please help me out
here is my html
<tbody data-ng-repeat="invoice in relatedInvoices>
<tr>
<td class="td-bottom-border">
{{invoice.PayableCurrencyCode}} {{invoice.PayablePaidAmount | number: 2}}<br />
<small>
<a data-ng-click="isOpenPayablePayments[$index] = !isOpenPayablePayments[$index]; togglePayablePayments(invoice.PayableInvoiceId)">Paid</a>
</small>
</td>
</tr>
<tr data-ng-show="isOpenPayablePayments[$index]">
<td>
<table>
<thead>
<tr>
<th>Transaction Id</th>
</tr>
</thead>
<tbody>
<tr data-ng-repeat="payment in payablePayments">
<td>{{payment.TransactionId}}</td>
</tr>
</tbody>
</table>
</td>
</tr>
</tbody>
Here is my javascript
var getPayments = function (invoiceId) {
paymentService.getPayments(invoiceId).then(function (paymentsResponse) {
return paymentsResponse.data;
});
};
$scope.togglePayablePayments = function(invoiceId) {
$scope.payablePayments = getPayments(invoiceId);
};
If I understood correctly, you want to have "payablePayments" for every invoice.
This is working: http://plnkr.co/edit/cj3jxZ?p=info
Try something like
// init at beginning
$scope.payablePayments = [];
$scope.togglePayablePayments = function(invoiceId) {
$scope.payablePayments[invoiceId] = getPayments(invoiceId);
};
and then
<tr data-ng-repeat="payment in payablePayments[invoice.PayableInvoiceId]">
Otherwise you overwrite the object for the preceding invoice.

ng-click function not recognzing changes inside table data

i created a table with one editable column. i want users to be able to save changes in this column cells, but though the call executes and sends the correct data before the change, it won't recognize changes in the table after data loaded.
this is how i create table:
<table class="table table-bordered table-hover" ng-controller="tableCtrl"
ng-controller="Ctrl">
<thead>
<td>user name</td>
<td>script name</td>
<td>cron format</td>
</thead>
<tbody ng-repeat="(user_id, row) in data | filter:search">
<tr ng-repeat="(script_id, cron_format) in row ">
<td ng-model="user_name">{{user(user_id)}}</td>
<td ng-model="script_name">{{script(script_id)}}</td>
<td ng-model="cron_format">
<span contenteditable="true"
ng-repeat="l in letters(cron_format) track by $index"
>{{l}}</span>
<button class="save"
ng-click="saveCron(user_id,script_id,cron_format)">save</button></td>
</tr>
</tbody>
</table>
the result is this table:
and cron format is editable. but when i call saveCron(user_id,script_id,cron_format)
it sends the values initialized the table.
this is the saveCron function:
$scope.saveCron = function(userId,scriptId,cronFormat){
$.post("updateCronChange.php","user_id=userId&script_id=scriptId&cron=cronFormat", function(data){
//function gets correct params
document.getElementById("demo").innerHTML = userId + scriptId +cronFormat;
});
}
how can i make it send the modified cron_format after end user changed it? thanks..

Categories

Resources