mthecreator
mthecreator

Reputation: 784

AngularJS ng-repeat issue and add row dynamically on button click

I want to create a simple form with some nested data. When I click the addSite() function, I want to create a new Site item and append it to my $scope.info.

I cannot create more than one form and the $index variable is not be passed to the scope. Here is a,

plunkr link.

HTML

<!DOCTYPE html>
<html>

  <head>
    <script data-require="[email protected]" data-semver="1.5.8" src="https://opensource.keycdn.com/angularjs/1.5.8/angular.min.js"></script>
    <link rel="stylesheet" href="style.css" />
    <script src="script.js"></script>
  </head>

  <body> 
  <div ng-app="myApp" ng-controller="myCtrl">

    <form>
      <label for="Domain Name">Domain Name</label>
      <input ng-model="info.name" type="text" /><br />
      <label for="IP">IP</label><input ng-model="info.ip" type="text" />
      <hr>
    <div ng-repeat="site in sites track by $index">
      <label for="">ID</label><input type="text" ng-model="site.id" />
      <label for="">title</label><input type="text" ng-model="site.title" />
      <label for="">desc</label><input type="text" ng-model="site.meta_desc" />
      <label for="">meta_keys</label><input type="text" ng-model="site.meta_keys" />


    </div>
      <br />
      <button ng-click="addSite()">Add Site</button>
    </form>

      <pre>
        {{info | json}}

      </pre>


</div>

script.js

angular.module('myApp', [])
.controller('myCtrl', function($scope){
  $scope.info = {};
  $scope.info.sites = {};


  $scope.addSite = function(){
    $scope.info.sites = {id:'',
                         title:'',
                         meta_desc:'',
                         meta_keys:''
    }

}


});

Data which I try to generate:

{
  "name": "myDomain",
  "ip": "11.22.33.44.55",
  "sites": {
    {"id": "1" ,"title": "myTitle Site 1","meta_desc": "myDescription Site 1", "meta_keys": ["my", "meta", "keys"]},
    {"id": "2" ,"title": "myTitle Site 2","meta_desc": "myDescription Site 2", "meta_keys": ["my", "meta", "keys"]},
    {"id": "3" ,"title": "myTitle Site 3","meta_desc": "myDescription Site 3", "meta_keys": ["my", "meta", "keys"]}
},

}

Data which I get now:

{
  "sites": {
    "id": "",
    "title": "",
    "meta_desc": "",
    "meta_keys": ""
  },
  "name": "myDomain",
  "ip": "11.22.33.44.55"
}

Thanks a lot for any help.

Upvotes: 1

Views: 1199

Answers (1)

Aruna
Aruna

Reputation: 12022

You have done few things wrong as below.

  1. Your ng-repeat="site in sites track by $index" is iterating sites instead of info.sites as in your $scope.info.sites
  2. Also $scope.info.sites should be an array like $scope.info.sites = [] instead of object which you have like $scope.info.sites = {}
  3. On addSite method instead of adding a new item to the array with $scope.info.sites.push(), you are overwriting the value by assigning it.

It worked after correcting the above stuffs.

angular.module('myApp', [])
    .controller('myCtrl', function($scope){
      $scope.info = {};
      $scope.info.sites = [];
      
      
      $scope.addSite = function(){
        $scope.info.sites.push({id:'',
                             title:'',
                             meta_desc:'',
                             meta_keys:''
        });
  
     };
      
      
    });
<!DOCTYPE html>
<html>

  <head>
    <script data-require="[email protected]" data-semver="1.5.8" src="https://opensource.keycdn.com/angularjs/1.5.8/angular.min.js"></script>
    <link rel="stylesheet" href="style.css" />
    <script src="script.js"></script>
  </head>

  <body> 
  <div ng-app="myApp" ng-controller="myCtrl">
  
    <form>
      <label for="Domain Name">Domain Name</label>
      <input ng-model="info.name" type="text" /><br />
      <label for="IP">IP</label><input ng-model="info.ip" type="text" />
      <hr>
    <div ng-repeat="site in info.sites track by $index">
      <label for="">ID</label><input type="text" ng-model="info.id" />
      <label for="">title</label><input type="text" ng-model="site.title" />
      <label for="">desc</label><input type="text" ng-model="site.meta_desc" />
      <label for="">meta_keys</label><input type="text" ng-model="site.meta_keys" />
      
      
    </div>
      <br />
      <button ng-click="addSite()">Add Site</button>
    </form>
      
      <pre>
        {{info | json}}
        
      </pre>
      
      
</div>

Method 2: (Using Object instead of array)

angular.module('myApp', [])
    .controller('myCtrl', function($scope){
      $scope.info = {};
      $scope.info.sites = {};
      
      
      $scope.addSite = function(){
        var index = Object.keys($scope.info.sites).length;
        $scope.info.sites['item' + index] = {id:'',
                             title:'',
                             meta_desc:'',
                             meta_keys:''
        };
  
     };
      
      
    });
<!DOCTYPE html>
<html>

  <head>
    <script data-require="[email protected]" data-semver="1.5.8" src="https://opensource.keycdn.com/angularjs/1.5.8/angular.min.js"></script>
    <link rel="stylesheet" href="style.css" />
    <script src="script.js"></script>
  </head>

  <body> 
  <div ng-app="myApp" ng-controller="myCtrl">
  
    <form>
      <label for="Domain Name">Domain Name</label>
      <input ng-model="info.name" type="text" /><br />
      <label for="IP">IP</label><input ng-model="info.ip" type="text" />
      <hr>
    <div ng-repeat="(idx, site) in info.sites track by $index">
      <label for="">ID</label><input type="text" ng-model="info.id" />
      <label for="">title</label><input type="text" ng-model="site.title" />
      <label for="">desc</label><input type="text" ng-model="site.meta_desc" />
      <label for="">meta_keys</label><input type="text" ng-model="site.meta_keys" />
      
      
    </div>
      <br />
      <button ng-click="addSite()">Add Site</button>
    </form>
      
      <pre>
        {{info | json}}
        
      </pre>
      
      
</div>

Upvotes: 2

Related Questions