Adding and deleting rows from one table to another - AngularJS

108 Views Asked by At

Our team is developing in ServiceNow and have a requirement to add rows from "Sending" table to "Receiving" table and delete rows from the "Receiving" table and return it back to the "Sending":

enter image description here

We've nailed down the adding portion of this exercise, but am having trouble getting the returning part to work correctly. Sometimes it will work completely fine. Other times, when we delete, it would uncheck the correct entry from the "Sending" table, but the entry would remain on the "Receiving" table.

On our "Sending" table, it is receiving the rootScope like this:

<tbody>
  <tr ng-repeat="item in data.list track by item.sys_id">
    <td ng-if="options.show_checkboxes">
      <input type="checkbox"
             ng-checked="item.isRowSelected"
             ng-click="toggleSelection(item);" >
    </td>
    <td role="cell" class="pointer sp-list-cell"
        ng-class="{selected: item.selected}"
        ng-click="go(item.targetTable, item)"
        ng-repeat="field in ::data.fields_array" data-field="{{::field}}"
        data-th="{{::data.column_labels[field]}}">
     <span ng-if="$first"
           aria-label="${Open record}: {{::item[field].display_value}}"
           role="link" tabindex="0">
       {{::item[field].display_value | limitTo : item[field].limit}}
       {{::item[field].display_value.length > item[field].limit ? '...' : ''}}
     </span>
     <span ng-if="!$first">
       {{::item[field].display_value | limitTo : item[field].limit}}
       {{::item[field].display_value.length > item[field].limit ? '...' : ''}}
      </span>
    </td>
  </tr>
</tbody>
$scope.selectedItems = [];
$scope.toggleSelection = function(item){
    item.isRowSelected = !item.isRowSelected;

    if(item.isRowSelected==false){ 
        $scope.allSelected=false;

        if($scope.selectedItems.indexOf(item.sys_id)!==-1){
            var add = $scope.selectedItems.indexOf(item.sys_id);
            $scope.selectedItems.splice(add,1);
        }
    } else {
        if($scope.selectedItems.indexOf(item.sys_id)==-1){
            $scope.selectedItems.push(
                item
            );
            $rootScope.$broadcast('moveItem', $scope.selectedItems);
        }
    }
}       

$rootScope.$on('deleteItem', function(event, data) {
    $scope.selectedItems = data;
});

In our "Receiving" table widget, our code looks like this:

<tbody>
  <tr ng-repeat="item in data.list2 track by item.sys_id">
    <td role="cell" class="pointer sp-list-cell"
        ng-class="{selected: item.selected}"
        ng-click="go(item.targetTable, item)"
        ng-repeat="field in ::data.fields_array"
        data-field="{{::field}}" data-th="{{::data.column_labels[field]}}">
      <span ng-if="$first"
            aria-label="${Open record}: {{::item[field].display_value}}"
            role="link" tabindex="0">
        {{::item[field].display_value | limitTo : item[field].limit}}
        {{::item[field].display_value.length > item[field].limit ? '...' : ''}}
      </span>
      <span ng-if="!$first">
         {{::item[field].display_value | limitTo : item[field].limit}}
         {{::item[field].display_value.length > item[field].limit ? '...' : ''}}
      </span>
    </td>
    <td>
       <a href="javascript:void(0)" ng-click="deleteSelection(item);">
         Remove
       </a>
    </td>
  </tr>
</tbody>
$scope.deleteSelection = function(item){
    item.isRowSelected =false;
    var minus = $scope.data.list2.indexOf(item.sys_id);
    $scope.data.list2.splice(minus, 1);
    $rootScope.$broadcast('deleteItem', $scope.data.list2);
}

$rootScope.$on('moveItem', function(event, data) {
    $scope.data.list2 = data;
    $scope.data.row_count = data.length;
});
2

There are 2 best solutions below

1
georgeawg On

Avoid $rootScope.$on — it risks memory leaks

In the course of its operation, AngularJS adds and removes DOM with their attached directives and controllers. The listener functions added by $rootScope.$on are not automatically removed when a directive or controller is removed. This can result in memory leaks and undesired behavior.

To avoid memory leaks, add event listeners to the $scope of the controller, not $rootScope:

̶$̶r̶o̶o̶t̶S̶c̶o̶p̶e̶.̶$̶o̶n̶(̶'̶d̶e̶l̶e̶t̶e̶I̶t̶e̶m̶'̶,̶ ̶f̶u̶n̶c̶t̶i̶o̶n̶(̶e̶v̶e̶n̶t̶,̶ ̶d̶a̶t̶a̶)̶ ̶{̶
$scope.$on('deleteItem', function(event, data) {
    $scope.selectedItems = data;
});

To avoid injecting $rootScope, use $scope.$root:

̶$̶r̶o̶o̶t̶S̶c̶o̶p̶e̶.̶$̶b̶r̶o̶a̶d̶c̶a̶s̶t̶(̶'̶m̶o̶v̶e̶I̶t̶e̶m̶'̶,̶ ̶$̶s̶c̶o̶p̶e̶.̶s̶e̶l̶e̶c̶t̶e̶d̶I̶t̶e̶m̶s̶)̶;̶
$scope.$root.$broadcast('moveItem', $scope.selectedItems);
0
Mohd. Abdul Sohail On

I've created a simple app in AngularJS.

Please have a look: https://stackblitz.com/edit/angularjs-mcqdzw?embed=1&file=home/home.html&view=preview

Hope this helps.