Angular JS UI-Grid Delete Row - angularjs

I'm new to ui-grid and I'm trying to implement a table in AngularJS as shown in the picture below. I'm trying to select a row and delete it using a delete button on that particular row. The ui-grid documentation requires us to use the gridApi but I can't find sufficient documentation for the same.

Please see a working example of how to delete a row here.
http://plnkr.co/edit/6TiFC6plEMJMD4U6QmyS?p=preview
The key is to use indexOf(row.entity) and not relying on row.index as it doesn't dynamically get updated.
$scope.deleteRow = function(row) {
var index = $scope.gridOptions.data.indexOf(row.entity);
$scope.gridOptions.data.splice(index, 1);
};
Generic approach
function deleteRow(row,grid) {
var i = grid.options.data.indexOf(row.entity);
grid.options.data.splice(i, 1);
}

You can use #Blousie solution as far as you adapt it to the newer API: https://github.com/angular-ui/ng-grid/blob/master/3.0_UPGRADE.md
Now "grid.appScope.edit(row.entity)" gives you access to your scope's "edit" function.
Something like this:
var removeTemplate = '<button class="btn btn-danger" ng-click="grid.appScope.removeRow(row)"><i class="glyphicon glyphicon-remove"></i></button>';
$scope.removeRow = function(row) {
var index = $scope.<yourDataModelProperty>.indexOf(row.entity);
if (index !== -1) {
$scope.<yourDataModelProperty>.splice(index, 1);
}
};

We need to use the $scope.grid.appScope. It is available in all templates. Besides that, you need to send the row object from the template, so that you can delete the row from the grid data.
jsfiddle: http://jsfiddle.net/3ryLqa9e/4/
cellTemplate:'<button class="btn primary" ng-click="grid.appScope.Delete(row)">Delete Me</button>'
$scope.Delete = function(row) {
var index = $scope.gridOptions.data.indexOf(row.entity);
$scope.gridOptions.data.splice(index, 1);
};

The other solutions provided here didn't worked for me(May be because of my latest different version of ui-grid). So removing element from the scope array worked for me. This should even work with other versions of ui-grid because grid must be updated when the data changes. (Thanks to Angular!!!)
I am using lodash to remove element from array and here is sample code:
$scope.deleteRow = function(row){
_.remove($scope.gridData, {
id: row.id
});
};

Just remove the row you want to delete from ui-grids data source model using splice.
For example
$scope.myGridOptions.data.splice(<YOUR ROW INDEX HERE>, 1);

Related

ui grid returning rows in the same order they are selected?

Hi am using UIgrid in an angularjs project and when I call the method gridApi.selection.getSelectedRows() to get the selected rows it returns an array with all the rows but in a random order. Ideally I want to get the rows in the same order they were selected (as if gridApi.selection.getSelectedRows() is backed by a queue) . Any idea how to achieve this please ?
This link to plunker shows the issue http://plnkr.co/edit/gD4hiEO2vFGXiTlyQCix?p=preview
You can implement the queue by yourself. Something like
$scope.gridOnRegisterApi = function(gridApi) {
gridApi.selection.on.rowSelectionChanged($scope, function(row) {
var selections =gridApi.selection.getSelectedRows();
// add sorted
selections.forEach(function(s){
if ($scope.mySelections.indexOf(s) === -1) {
$scope.mySelections.push(s);
}
});
// remove the ones that are not selected (use for to modify collection while iterating)
for (var i = $scope.mySelections.length; i >0; i--) {
if (selections.indexOf($scope.mySelections[i]) === -1) {
$scope.mySelections.splice(i, 1);
}
}
console.log($scope.mySelections);
row.entity.firstSelection = false;
if (row.isSelected) row.entity.firstSelection = (gridApi.selection.getSelectedCount() == 1);
});
};
I think there is a bug with that version of angular I was using there , if you upgrade the version in the plnkr to 1.6.1 it will behave as expected

bootstrap selectpicker and cloning

I have been using bootstrap selectpicker where I've added an Add Button for user to replicate the button as much as he wants. Problem is, selectpicker is not working on the second / cloned element and values of dropdown are just showing and not changing on click.
Main Select:
<div id="main_product">
<select name="product[]" class="selectpicker" >
<option value="Tube Lights" >Tube Lights</option>
<option value="Downlights" >Downlights</option>
</select>
</div>
Clone Function:
function clone()
{
var $orginal = $('#main_product');
var $cloned = $orginal.clone();
$cloned.appendTo('#new_products');
// $cloned.find('.bootstrap-select').remove();
// $cloned.find('select').selectpicker();
}
Note that I tried to reassign the selectpicker to the cloned object which is in comments atm, because it dint work also.
Any help would be really appreciated.
I came across this problem but if using the latest version now the select is placed inside the .bootstrap-select element for html5 error handling purposes. The remove() also removes the select, a work around is:
Instead of:
$cloned.find('.bootstrap-select').remove();
Use:
$cloned.find('.bootstrap-select').replaceWith(function() { return $('select', this); });
This will replace the .bootstrap-select element with the select element that it contains inside.
function clone()
{
//you can use :
var $orginal = $('#main_product');
var $cloned = $orginal.clone();
//Or
var $cloned = $('#main_product').clone();
//then use this to solve duplication problem
$cloned.find('.bootstrap-select').replaceWith(function() { return $('select', this); })
$cloned .find('.selectpicker').selectpicker('render');
//Then Append
$cloned.appendTo('#new_products');
}
if we replace the bootstrap-select with the select then the problem is in HTML structure.
so, original element is actual bootstrap-select and cloned are normal select.
take look at following for more clarification.
instead of this
$cloned.find('.bootstrap-select').replaceWith(function() { return $('select', this); });
use
$cloned.selectpicker('refresh');
$cloned.find('.bootstrap-select:odd').remove();
You can please change clone function
function clone() {
var $orginal = $('#main_product');
var $cloned = $orginal.clone();
var $selectPicker = $cloned.find('select');
$cloned
.find('.bootstrap-select').remove().end()
.append($selectPicker).end();
$cloned.find('select').selectpicker();
$cloned.appendTo('#new_products');
}
When using in Form Sets along with other form fields you need to replace and render all the selectpicker mentioned by #cm_mehdi. First find the new form html element and apply the below code:
//Clone new form
let newForm = purchaseForm[0].cloneNode(true);
// Replace and render the cloned html selectpicker
$(newForm).find('.bootstrap-select').replaceWith(function() { return $('select', this); })
$(newForm).find('.selectpicker').selectpicker('render');
// Re-Initialize search in dropdown
$(`#id_form_formfield-${formNum}`).selectpicker({liveSearch: true});

How to get the value of selected row directly in HTML using ag-grid

i try to get the the value of number row selected, and print it in HTML using Angularjs, but no issue,
i have the count only when i clic in the grid column header.
The value of " selectedRowsCounter " is 0 in html, when i dosn't clic in the grid header
my code is like
var activeButtons = function() {
var countRowsSelected = $scope.gridOptions.api.getSelectedRows().length;
$scope.selectedRowsCounter = countRowsSelected;
console.log($scope.selectedRowsCounter);
$rootScope.count.selectedRows = countRowsSelected;
};
$scope.gridOptions = {
rowData: null,
angularCompileRows: true,
onSelectionChanged: activeButtons,
}
there is a screenshot
i have open the same subject here
https://github.com/ceolter/ag-grid/issues/1023
i have added this line to activeButtons function and it work fine
$scope.gridOptions.api.refreshView();
i dont knew if there is a good solution, but that work for now
The problem seems to be with Angular being unaware of the $scope property change because ag-grid does not tell Angular that it has modified something in the $scope. Although it is difficult to tell if you don't show your view.
You can use onSelectionChanged the way you are using it to know how many rows have been selected, but you need to tell Angular that something has changed in its $scope by applying it.
Something like this:
var activeButtons = function() {
var countRowsSelected = $scope.gridOptions.api.getSelectedRows().length;
$scope.selectedRowsCounter = countRowsSelected;
console.log($scope.selectedRowsCounter);
$rootScope.count.selectedRows = countRowsSelected;
window.setTimeout(function() {
this.$scope.$apply();
});
};
That way you can apply the $scope and the html view will reflect the changes.

Angular ng-repeat not updating after splice

I am working on a Angular Material site and using ng-repeat to populate a table. The list generated by the ng-repeat contains a list of users (the users array is populated by a RESTFul query).
Each "item-content" of the ng-repeat has a "Delete" button to delete/splice the item/user out of the array.
If I have no filters applied to the ng-repeat statement...when I splice the index of the selected user out of the array....the UI/DOM is updated and the user is removed from the list.
If I apply a filter (filters by the first letter of the last name and only shows those results)...when I splice the index out of the array...the UI/DOM is NOT updated and user remains in the list (from what I can tell from walking through the delete function from the console...the array is updated and the index/user is removed).
I filter being used is a custom angular filter and takes one input (the starting letter of the last name you want to filter on).
app.filter('startsWith', function () {
return function (items, letterMatch) {
var re = new RegExp("^[" + letterMatch.toUpperCase() + letterMatch.toLowerCase() + "]$");
var filtered = [];
for (var i = 0; i < items.length; i++) {
var item = items[i];
var lastNameLetter = item.user.name.substr(item.user.name.indexOf(' ') + 1, 1);
if (re.test(lastNameLetter)) {
filtered.push(item);
}
}
return filtered;
};
});
Here is the ng-repeat statement:
<md-item ng-repeat="user in ddUsers | startsWith:selectedFilter | startFrom:currentPage*pageSize | limitTo:pageSize">
In the controller...I am using Dialog Prompt (part of the Angular Material 1.1 RC framework) to initiate/confirm the Delete and proceed with the splice.
$scope.showPrompt = function(ev,index,user) {
// Appending dialog to document.body to cover sidenav in docs app
var confirm = $mdDialog.prompt()
.title('Delete User?')
.textContent('Type in DELETE to confirm deletion of the user.')
.placeholder('DELETE')
.ariaLabel('Delete User')
.targetEvent(ev)
.ok('Delete')
.cancel('Cancel');
$mdDialog.show(confirm).then(function(result) {
if(result=="DELETE")
{
$scope.ddUsers.splice(index, 1);
$scope.showSimpleToast('Successfully deleted ' + user.user.name);
}
else
{
$scope.showSimpleToast('Did not confirm properly');
}
}, function() {
$scope.showSimpleToast('Cancelled deletion for ' + user.user.name);
//var message = $scope.filterLastName(user.user.name);
//$scope.showSimpleToast(message);
});};
When the controller loads...I have a init function that executes and populates ddUsers from a custom angular factory:
var init = function () {
$scope.ddUsers = $UserList.UserList;
}
init();
I am not sure why ng-repeat is not updating after the splice when a filter is applied. If I have no filter on the ng-repeat, ng-repeat does update the UI/DOM to reflect the change and you don't see the user anymore.
While it is not shown how you call the function I assume you are passing in $index from view.
The problem with doing that is that $index will not be the same index for filtered array as for the original array so you would be splicing the wrong element out of the main data array
You need to do your own indexing by passing in the actual object.
I will also assume that user is that object so you would do:
if(result=="DELETE")
{
var idx = $scope.ddUsers.indexOf(user);
if(idx > -1 ){// make sure can index this object
$scope.ddUsers.splice(idx, 1);
$scope.showSimpleToast('Successfully deleted ' + user.user.name);
else{
// Ooops ... can't find it
}
}

Remove item from list after filtering

I have the following issue:
I've create a list that allow the user to delete an item from list, as following:
When user click on trash icon, the item is removed normally.
The problem is when the user uses the filter on top.
In that case, if I delete the number 6565 (index 4 in original list, 1 on filtered list), the item deleted is on index 1 on original list, resulting on delete the register with number #564456
This is my delete call on click:
$scope.deleteOwn = function (uuid) {
console.log(uuid);
var coupon = $scope.ownsCoupons[uuid];
Coupon.delete({'id' : coupon.uuid}, function () {
$scope.ownsCoupons.splice(uuid, 1);
});
}
And this is my html template:
<td></i></td>
I also try to use the code: $scope.ownsCoupons.splice(coupon, 1);without success.
Does anyone know how to fix that?
I've coded using the following reference: AngularJS How to remove an Item from scope
[EDIT]
I've created a Plunker to this: http://plnkr.co/edit/Fhxp6uZyTJCY05CAQ7yA?p=preview
As mentioned by #pkozlowski.opensource, you can't depend on $index to identify an item in an array in this way. I would make the following changes:
HTML:
<td><a ng-click="deleteWish(coupon)"><i class="icon-trash"></i></a></td>
JS:
$scope.deleteWish = function (coupon) {
var index = $scope.coupons.indexOf(coupon);
if (index != -1) {
$scope.coupons.splice(index, 1);
}
}
Here is a working Plunker: http://plnkr.co/edit/b0b2cYGsM5wtw8hIrQB5?p=preview

Resources