0

I have created a dynamic table that allows the user to add rows to the table. Now I want to create multiple tables that allow the user to add multiple rows. The problem with my code is that the 'variable' choice is shared and making any changes to any of the fields in any of the tables causes all the table fields to replicate the behaviour. Can someone tell me how to create tables that are capable of holding different values?

Angular.html

<html>
<head>
    <link rel="stylesheet" type="text/css" href="createQuiz.css" />
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.7.8/angular.min.js">
    </script>
    <script src="quizMgmt.js"></script>
</head>
<body>
    <div ng-app="angularjs-starter" ng-controller="MainCtrl">
        <form action="/createQuiz">
        <ul class="list-group" data-ng-repeat="path in path">
            <span>
                <h1 ng-model="colNum" >Path {{colNum}}</h1>
                <button  class="btn btn-primary" ng-click="addNewPath()">Add New Path</button>
            </span>
            <li class="list-group-item" data-ng-repeat="choice in choices">
                <span>
                    <span class="col-sm-2">
                        <select class="form-control" ng-model="choice.type" name="item" ng-options="item for item in selectOptions">
                        </select>
                    </span><br>
                    <span class="col-sm-9">
                        <input class="form-control" type="text" ng-model="choice.name" name="value" placeholder="Enter mobile number">
                    </span>
                    <button class="btn btn-danger" ng-click="removeChoice(choice.id)" ng-if="choice.id!=index">-</button>

                    <button class="btn btn-danger" ng-click="addNewChoice()" ng-if="choice.id===index">+</button>
                </span>
            </li>
        </ul>   
        <br>  
        <button  class="btn btn-primary" ng-click="addNewChoice()">Add fields</button>
        <input type="submit">
        </form>
        <br>
        <br>
        <div id="choicesDisplay">
            <!-- {{ choices }} -->
            {{path}}
        </div>
    </div>
</body>

quizMgmt.js

    var app = angular.module('angularjs-starter', []);
  app.controller('MainCtrl', function($scope) {
    $scope.selectOptions = ["Mobile",
                            "Office",
                            "Home"     
    ];

  $scope.choices = [{"id": 1,"type":"Mobile","name":""}, 
                    {"id": 2,"type":"Mobile","name":""}];

  $scope.path =[{"NumPath":1, 'path':$scope.choices}];

  $scope.colNum=1;
  $scope.index = $scope.choices.length;

  $scope.addNewChoice = function() {
    var newItemNo = ++$scope.index;    
    $scope.choices.push({'id':newItemNo, "type":"Mobile","name":""});


  };

  $scope.addNewPath= function() {  
    var NumPath=$scope.path.length;
    console.log($scope.path.length)  
    $scope.colNum=NumPath; 
    $scope.path.push({"NumPath": NumPath,'path':$scope.choices});    

  };

  $scope.removeChoice = function(id) {

        if($scope.choices.length<=1){
            alert("input cannot be less than 1");
            return;
        }


        var index = -1;
            var comArr = eval( $scope.choices );
            for( var i = 0; i < comArr.length; i++ ) {
                if( comArr[i].id === id) {
                    index = i;
                    break;
                }
            }
            if( index === -1 ) {
                alert( "Something gone wrong" );
            }
            $scope.choices.splice( index, 1 );
  };

});

2 Answers 2

2

Issue is with the $scope.choices which is common object , So it is getting replicated.

$scope.choices must be isolated and restrict it to that respective path like below. I believe by default you need to two choices while adding new path. Hope this helps.

var app = angular.module('angularjs-starter', []);
  app.controller('MainCtrl', function($scope) {
    $scope.selectOptions = ["Mobile",
                            "Office",
                            "Home"     
    ];
    
      $scope.getDefaultChoices = function() {
      return [{"id": 1,"type":"Mobile","name":""}, 
                    {"id": 2,"type":"Mobile","name":""}];
      };

  $scope.choices = $scope.getDefaultChoices();

  $scope.paths = [{"NumPath":1, 'choices':$scope.choices}];

  $scope.colNum=1;
  $scope.index = $scope.choices.length;

  $scope.addNewChoice = function(path) {
    var newItemNo = ++$scope.index;    
    path.choices.push({'id':newItemNo, "type":"Mobile","name":""});


  };

  $scope.addNewPath= function() {  
    var NumPath=$scope.paths.length;
    console.log($scope.paths.length)  
    $scope.colNum=NumPath; 
    $scope.paths.push({"NumPath": NumPath,'choices':              $scope.getDefaultChoices() });    

  };
 

  $scope.removeChoice = function(path, id) {

        if(path.choices.length<=1){
            alert("input cannot be less than 1");
            return;
        }


        var index = -1;
            var comArr = eval( path.choices );
            for( var i = 0; i < comArr.length; i++ ) {
                if( comArr[i].id === id) {
                    index = i;
                    break;
                }
            }
            if( index === -1 ) {
                alert( "Something gone wrong" );
            }
            path.choices.splice( index, 1 );
  };

});
<html>
<head>
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.7.8/angular.min.js">
    </script>
</head>
<body>
    <div ng-app="angularjs-starter" ng-controller="MainCtrl">
        <form>
        <ul class="list-group" data-ng-repeat="path in paths">
            <span>
                <h1 ng-model="colNum" >Path {{colNum}}</h1>
                <button  class="btn btn-primary" ng-click="addNewPath()">Add New Path</button>
            </span>
            <li class="list-group-item" data-ng-repeat="choice in path.choices">
                <span>
                    <span class="col-sm-2">
                        <select class="form-control" ng-model="choice.type" name="item" ng-options="item for item in selectOptions">
                        </select>
                    </span><br>
                    <span class="col-sm-9">
                        <input class="form-control" type="text" ng-model="choice.name" name="value" placeholder="Enter mobile number">
                    </span>
                    <button class="btn btn-danger" ng-click="removeChoice(path, choice.id)" ng-if="choice.id!=index">-</button>

                    <button class="btn btn-danger" ng-click="addNewChoice(path)" ng-if="choice.id===index">+</button>
                </span>
            </li>
        </ul>   
        <br>  
        <button  class="btn btn-primary" ng-click="addNewChoice(path)">Add fields</button>
        </form>
        <br>
        <br>
        <div id="choicesDisplay">
            <!-- {{ choices }} -->
            {{path}}
        </div>
    </div>
</body>

Sign up to request clarification or add additional context in comments.

Comments

1

The issue is with choices object. As you are using same instance in multiple objects so as new table created data get copied. The solution of this is to create new instance of choices when new table gets created using angular.copy

NOTE: I didn't understand why you added "Add Fields" outside the list as it doesn't make any sense when you create new tables dynamically.

I have made few changes in the code kindly refer below.

var app = angular.module('angularjs-starter', []);
  app.controller('MainCtrl', function($scope) {
    $scope.selectOptions = ["Mobile",
                            "Office",
                            "Home"     
    ];

  $scope.choices = [{"id": 1,"type":"Mobile","name":""}, 
                    {"id": 2,"type":"Mobile","name":""}];

  $scope.path = [{"NumPath":1, 'path':angular.copy($scope.choices)}];

  $scope.colNum=1;

  $scope.addNewChoice = function(path) {
    var newItemNo = path.path.length;    
    path.path.push({'id':++newItemNo, "type":"Mobile","name":""});


  };

  $scope.addNewPath= function() {  
    var NumPath=$scope.path.length;
    console.log($scope.path.length)  
    $scope.colNum=NumPath+1; 
    $scope.path.push({"NumPath": NumPath+1,'path':angular.copy($scope.choices)});    

  };

  $scope.removeChoice = function(id, path) {
		path.splice(id-1, 1);
		// re-initialize choice id
		angular.forEach(path, function(o, index){
			o.id = index+1;
		})
  };

});
<html>
<head>
    <link rel="stylesheet" type="text/css" href="createQuiz.css" />
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.7.8/angular.min.js">
    </script>
	
    <script src="quizMgmt.js"></script>
</head>
<body>
    <div ng-app="angularjs-starter" ng-controller="MainCtrl">
        <ul class="list-group" data-ng-repeat="path in path">
            <span>
                <h1 ng-model="colNum" >Path {{colNum}}</h1>
                <button  class="btn btn-primary" ng-click="addNewPath()">Add New Path</button>
            </span>
            <li class="list-group-item" data-ng-repeat="choice in path.path">
                <span>
                    <span class="col-sm-2">
                        <select class="form-control" ng-model="choice.type" name="item" ng-options="item for item in selectOptions">
                        </select>
                    </span><br>
                    <span class="col-sm-9">
                        <input class="form-control" type="text" ng-model="choice.name" name="value" placeholder="Enter mobile number">
                    </span>
                    <button class="btn btn-danger" ng-click="removeChoice(choice.id, path.path)" ng-if="choice.id!=path.path.length">-</button>

                    <button class="btn btn-danger" ng-click="addNewChoice(path)" ng-if="choice.id===path.path.length">+</button>
                </span>
            </li>
			<br/>
			<br/>
			<button  class="btn btn-primary" ng-click="addNewChoice(path)">Add fields</button>
        </ul>   
        <br>  
        
        
        <br>
        <br>
        <div id="choicesDisplay">
            <!-- {{ choices }} -->
            {{path}}
        </div>
    </div>
</body>

Good day :)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.