1

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="angularjs@1.5.8" 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.

Aruna
  • 11,441
  • 3
  • 24
  • 39
mthecreator
  • 734
  • 1
  • 7
  • 17

1 Answers1

2

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="angularjs@1.5.8" 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="angularjs@1.5.8" 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>
Aruna
  • 11,441
  • 3
  • 24
  • 39
  • Thanks for your fast answer Aruna. Please can you explain me point 2. Why do we need to pass an array instead of an object. it wonders me that it is not possible in angular to easyliy concatenate 2 objects. In angularjs are methods like merge and extend. Is it not a scenario for using this methods or i am wrong? thanks a lot – mthecreator Nov 22 '16 at 02:49
  • Objects work with the key and won't work, if it does not have any key. In your data `"sites": { {"id": "1"}, {"id": "2} }`, this is an invalid object, since the parent object does not have any key for the child it has. To be a valid object, it should be like this with a key, `"sites": { "item1": {"id": "1"}, "item2": {"id": "2} }` . If you don't have any key then, it should be an array as `"sites": [ {"id": "1"}, {"id": "2} ]` – Aruna Nov 22 '16 at 02:55
  • okay, it is possible to reproduce the object like this `"sites": { "item1": {"id": "1"}, "item2": {"id": "2} }` or does it make sense at all? – mthecreator Nov 22 '16 at 03:15
  • Okay, I will make the change. – Aruna Nov 22 '16 at 03:16
  • I have updated the code. You can check the method 2 below – Aruna Nov 22 '16 at 03:21
  • Okay thanks a lot Aruna, this is enough to go on. Wich method would you prefer? – mthecreator Nov 22 '16 at 03:26
  • I would prefer array with ng-repeat unless there is a reason for this to go with the object :-) – Aruna Nov 22 '16 at 03:28
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/128666/discussion-between-mvmthecreator-and-aruna). – mthecreator Nov 22 '16 at 03:31
  • 1
    @Hema, Do you mean something like this, http://stackoverflow.com/a/9593447/7055233 – Aruna Apr 19 '17 at 00:45
  • @Aruna, i have referred question which you suggested,Can you please help me with this http://stackoverflow.com/questions/43487344/saving-nested-json-data-into-mysql-db-using-spring-hibernate – Hema Apr 19 '17 at 05:46