Ahmad Shli
Ahmad Shli

Reputation: 69

Issue with angular.element using counter of elements

I am developing an application using AngularJS. In some part of my application, I have a button, when I click that button it adds a new input to add telephone. With each input, there is a remove link to delete that input.

With my code, I am using counter.

For some reasons, I am not able to get it right!!

View:

<div id="div{{$index}}" style='z-index: 1' ng-repeat="cEdit in telephone" ng-show="contactsElements">
    <input type="text" ng-model="cEdit" maxlength="15">
    <a href="javascript:void(0)" ng-click="removeDIV($index)">Remove</a>
</div>
<div ng-show="contactsElements">
    <div id="space-for-new-telephones"></div>
    <button ng-click="addDIV()">Add</button>
</div>

JS:

$scope.removeDIV = function (arrAddr) {
    console.log("Array Index = " + arrAddr);
    var iEl = angular.element(document.querySelector('#div' + arrAddr));
    iEl.remove();
    if ($scope.count > 0) {
        $scope.count = $scope.count - 1;
        console.log($scope.count);
    }                
}

$scope.addDIV = function () {
    if ($scope.count <= 2) {
        angular.element(document.getElementById('space-for-new-telephones')).append("<div id='div" + $scope.count + "'><input type='text' ng-model='$scope.telephone.num[" + $scope.count + "]' maxlength='15'>&nbsp;<a href='javascript:void(0)' ng-click='removeDIV(" + $scope.count + ")'>Remove</a></div>");
        $scope.count++;
        console.log($scope.count);
    }        
}

My problem is with the input that I manually add them by pressing the button... It looks like I have a problem with the append command.

ng-click='removeDIV(" + $scope.count + ")'

I am able to add the element and display it in the view, but cannot remove it later.

Please note that the element that already in the view using ng-repeat are working properly and I am able to remove them.

Upvotes: 1

Views: 590

Answers (4)

Janko
Janko

Reputation: 202

<div style='z-index: 1' ng-repeat="cEdit in telephone" ng-show="contactsElements">
<input type="text" ng-model="phone.number" maxlength="15">
<a href="javascript:void(0)" ng-click="remove(telephone, $index)">Remove</a> 
</div>
<div ng-show="contactsElements">
<div id="space-for-new-telephones"></div>
<button ng-click="add(telephone, phone)">Add</button>                                                
</div>


$scope.remove = function (telephone, $index) {
    delete telephone[$index];
}

$scope.add= function (telephone, phone) {
   telephone.push(phone)
}

You have bad idea about how angular works

EDIT:
Well, I recomend You to take a look at this working fiddle there is all You want to know.

Sentence You present is working, but wrong answer my friend!

I recomend, to not use splice as removal from array, becouse there is a problem with reindexing.
Imagine that You push a delete button, and item with index 0 is removed when $http request was resolved. And all is good as You do it once!


When You hit this button 3 times and all these resolve will be waiting for resolve, there is thread that wrong item will be removed

And now I hope You will appreciate this exaple of approche with splice on specially edited by my for You fiddle


the thing is press second button 3 times quickly and take a look what just happened.

I got a lot of exp in angular. Dont blame me for telling truth my friend, hope You got this lesson

Upvotes: -1

Yan Yang
Yan Yang

Reputation: 1974

  1. Your id="div{{$index}}"s should be wrapped into "space-for-new-telephones", or maybe you can just call it "space-for-telephones" or you can remove the wrapper.
  2. You don't have to manipulate doms(view) when inserting a new telephone feild like angular.element(document.getElementById('space-for-new-telephones')).append("<div id='div" + $scope.count + "'><input type='text' ng-model='$scope.telephone.num[" + $scope.count + "]' maxlength='15'>&nbsp;<a href='javascript:void(0)' ng-click='removeDIV(" + $scope.count + ")'>Remove</a></div>");. Just modify the model and the "view" will change accordingly.$scope.telephones.push("");
  3. The same as 2, removing a telephone field should also be realised by manipulating the model: $scope.telephone.splice(arrAddr,1);
  4. Use track by to avoid error reporting when you have duplicate telephone numbers, and use ng-model="telephone[$index]" to synchronise between inputs and models on $scope immediately.

So the codes should be:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>test</title>
</head>
<body ng-app="teleApp" ng-controller="tele">
    <div id="div{{$index}}" style='z-index: 1' ng-repeat="cEdit in telephone track by $index" ng-show="contactsElements">
        <input type="text" ng-model="telephone[$index]" maxlength="15">
        <a href="javascript:void(0)" ng-click="removeDIV($index)">Remove</a>
    </div>
    <div ng-show="contactsElements">
        <button ng-click="addDIV()">Add</button>
    </div>
</body>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.7/angular.min.js"></script>
<script src="index.js"></script>
</html>

JS codes:

var teleApp = angular.module("teleApp", []);
teleApp.controller("tele",function($scope){
    $scope.contactsElements = true;
    $scope.count = 0;
    $scope.telephone = [
    ]

    $scope.removeDIV = function (arrAddr) {
        console.log("Array Index = " + arrAddr);
        $scope.telephone.splice(arrAddr,1);
        if ($scope.count > 0) {
            $scope.count = $scope.count - 1;
            console.log($scope.count);
        }
    }

    $scope.addDIV = function () {
        if ($scope.count <= 2) {
            $scope.telephone.push('');
            $scope.count++;
            console.log($scope.count);
        }
    }
})

Upvotes: 0

Abu Sufian
Abu Sufian

Reputation: 157

Not tried running your code but I think the following code will solve your problem

    var html = "<div id='div" + $scope.count 
      + "'><input type='text' ng-model='$scope.telephone.num[" 
      + $scope.count + "]' maxlength='15'>&nbsp;"
      +"<a href='javascript:void(0)' ng-click='removeDIV(" 
      + $scope.count + ")'>Remove</a></div>"

    angular.element(document.getElementById('space-for-new-telephones'))
    .append($compile(html)($scope));

Upvotes: 1

Hugo Silva
Hugo Silva

Reputation: 6938

You shouldn't manipulate the DOM like that with angular. You should manipulate data in your code, and have the DOM reflect those changes for you. Just like you are doing in the first div in your code with ng-repeat="cEdit in telephone". You can create an array in your $scope to hold all the new telephones. Then add and remove items from the array, using ng-repeat to render the existing items, instead of append and remove.

If you do need to manipulate the DOM, you should use directives - https://docs.angularjs.org/guide/directive

Here is some further information about the DOM manipulation concept - http://tech.zumba.com/2014/08/02/angularjs-forget-jquery/

Upvotes: 1

Related Questions