1

enter image description hereI have a query regarding angularjs, i.e. I have a table in which I have rows, but these rows are dynamically inserted by user. That means If I have a company having more than one owners then I allow them to add as many owners as they want by simply clicking on add button which is placed with the textboxes (i.e. name, email, number textboxes) I have used 'ng-repeat' on a row so that the list of owners can be dynamically added one by one. While fetching values from the database it is working perfectly fine but when I am trying to add values by clicking 'add' button, It adds the new row with all the text boxes BUT WITH THE SAME VALUES as the previous row. I think it is because I have used ng-model to link the data.. but then that is the only option I can bind the data.. Do anyone have solution for this problem.? Please help me. Thank you in advance I am sharing the code sample for better understanding,

JSP code:

<tbody id="insertionRow">
    <tr>
        <th>#</th>
        <th class="required">Name</th>
        <th>Email</th>
        <th>Phone No</th>
        <th>Add</th>
        <th>Delete</th>

    </tr>
    <tr data-ng-repeat="c in ctrl.client.clientOwnerVOList">
        <td>{{$index + 1}}</td>

        <td class="col-lg-3"><input type="Text"
            class="form-control"
            data-ng-model="c.clientOwnerName"
            name="clientOwnerName{{$index + 1}}" id="Name">

            </td>

        <td class="col-lg-4"><input type="Email"
            class="form-control"
            data-ng-model="c.clientOwnerEmail"
            name="clientOwnerEmail{{$index + 1}}" id="Email"></td>

        <td class="col-lg-3"><input type="Text"
            class="form-control"
            data-ng-model="c.clientOwnerPhone"
            name="clientOwnerPhone{{$index + 1}}" id="PhoneNo"></td>

        <td> 
        <button type="button"
                data-ng-click="insert();"
                class="btn btn-sm btn-default">
                <i class="fa fa-plus fa-lg"></i>
            </button></td>

        <td><button type="button"
                    onClick="$(this).closest('tr').remove();"
                class="btn btn-sm btn-default">
                <i class="fa fa-trash fa-lg "></i>
            </button></td>

    </tr>
</tbody>

AngularJS controller code:

$scope.insert = function(){
  var tableRow ="<tr data-ng-repeat='c in ctrl.client.clientOwnerVOList'>"+ 
    "<td>"+i+"</td>"+
    "<td class='col-lg-3'><input type='Text' class='form-control' data-ng-model='c.clientOwnerName' name='clientOwnerName{{$index + 1}}' ></td>"+
    "<td class='col-lg-4'><input type='Email' class='form-control' data-ng-model='c.clientOwnerEmail' name='clientOwnerEmail{{$index + 1}}'</td>"+
    "<td class='col-lg-3'><input type='Text' class='form-control' data-ng-model='c.clientOwnerPhone' name='clientOwnerPhone{{$index + 1}}' ></td>"+
    "<td><button type='button' data-ng-click='insert()' class='btn btn-sm btn-default'><i class='fa fa-plus fa-lg'></i></button></td>"+
    "<td><button type='button' class='btn btn-sm btn-default' onClick=$(this).closest('tr').remove();><i class='fa fa-trash fa-lg '></i></button></td>"+
    "</tr>";

  var compiledString = $compile(tableRow)($scope);

  $("#insertionRow").append(compiledString);
    i++;
};

And the client Object is as follows

self.client= {
    clientID:'',
    clientName:'',
    clientDescription:'',
    clientAddressLine:'',
    clientContactPersonPhone:'',
    createdOn:'',
    astUpdatedOn:'',
    country:'',
    state:'',
    city:'',
    isDeleted:'',
    clientOwnerVOList: [
        {
            clientOwnerID:'',
            createdOn:'',
            isDeleted:'' ,                           
            clientOwnerName:'',
            clientOwnerPhone:'',
            clientOwnerEmail:''
        }
    ]
}
Vish
  • 280
  • 2
  • 18
  • Concept is all wrong. Push a new object to `client.clientOwnerVOList` and row in the view will be created for that new object in the array. This is a fundamental part of how angular works ... it manages the view for you based on your controller models – charlietfl May 30 '16 at 11:48
  • You can do this in a simple way! You can create a custom directive with isolate scope, and pass the values that''s it. – sajan May 30 '16 at 11:53
  • @Charlietfl I understood your view, but as per my knowledge when I click on the delete button the corresponding object should be deleted., can u suggest how can I achieve that? – Vish May 30 '16 at 12:00
  • You do the opposite...you remove item from array and angular will take care of removing row in view. See http://stackoverflow.com/questions/15453979/how-do-i-delete-an-item-or-object-from-an-array-using-ng-click/15454424#15454424 – charlietfl May 30 '16 at 12:02
  • Thank you charlietfl, you recommendations were useful too... – Vish May 30 '16 at 12:36

2 Answers2

0

The insert function is pretty strange. AFAIT you are inserting some compiled HTML into the DOM. Angular's whole thing is for you to avoid doing this by hand. You should be changing ctrl.client.clientOwnerVOList directly by appending the required JS objects to it and then the change will be reflected by the DOM.

The code should look similar to this, plus-minus application specific logic which you know better.

$scope.append = function() {
  self.client.clientOwnerVOList.push({
    clientOwnerId: 'newid',
    createdOn: 'today',
    isDeleted: 'false',
    clientOwnerName: 'foo',
    clientOwnerPhone: 'bar',
    clientOwnerEmail: 'foo@bar.com'
  });
}

The values to populate the client info would be taken from other places (other models fields, or some sensible defaults etc.)

Basically, you have a bunch of data (self.client, and any other controller variables from the scope). The view is a function of this data, and you describe how to build the DOM through the html template which can access the fields from the scope. It's Angular's job to figure out how to do that. Whenever some sort of event happens, like a button press or network event etc., you update the data, and then Angular rebuild the DOM for you.

Horia Coman
  • 8,681
  • 2
  • 23
  • 25
  • can you give me a demo for this? Actually I compiled it because the String to be appended contains click even, Until I compile it, I does not bind the event – Vish May 30 '16 at 11:43
0

I tried to reproduce your problem in this plunker : https://plnkr.co/edit/Eqw21bGNetGtHZIQZCYw?p=preview

I changed your insert function to create new clientOwnerVO.

I just push new object like this :

$scope.client.clientOwnerVOList.push({clientOwnerID:'',
              createdOn:'',
              isDeleted:'' ,                           
               clientOwnerName:''
              ,clientOwnerPhone:''
              ,clientOwnerEmail:'',});
                i++;

I hope i understand your problem

Silvinus
  • 1,445
  • 8
  • 16
  • I tried the same thing earlier, but the problem is the if I click on the delete button the corresponding object should be deleted from the list, you can try your own plunker by adding 4-5 entries then delete 3 of them and again try adding.. you will see flaws – Vish May 30 '16 at 12:02
  • On delete you need to remove the specified field from the array. – Horia Coman May 30 '16 at 12:09
  • I updated the plunker to bind a method to ng-click of delete button. But there is some mistake due to uses of $index. I recommend to you to manage index differently – Silvinus May 30 '16 at 12:13
  • Last thing, you doesn't need to touch the html dom. Angularjs manage dom from data include into scope. The only way to manipulate dom is in directive. If you keep that in memory you simplify your app – Silvinus May 30 '16 at 12:19
  • @Silvinus could you do me one more favour, What If I want Keep the First row Constant i.e. Blank and clicking on the add button the new row will be appended below the first constant row. and it should be disabled n have edit image instead of add. – Vish May 30 '16 at 13:39