Q:

ng-form not available after manually deleting an item from collection of ng-repeat

Edit Here is the plunk for this question
I have a master detail form for an accounting transaction.  The master portion just contains two fields name and Type.  The detail portion can have two or more entries and each entry has AccountId, Debit and Credit fields.  The form looks like

You can see that there is a delete button against each entry so if we have more than two entries we can delete any entry at random.  The form html looks like following
<body data-ng-app="transactions">
    <div data-ng-controller="transactionsController">
        <form role="form" name="transactionForm" novalidate data-ng-submit="create()">
            <div class="row">
                <div class="col-md-2">
                    &nbsp;
                </div>
                <div class="col-md-4">
                    <h2 class="form-login-heading">Create Transaction</h2>
                    <div data-ng-repeat="error in errors" class="alert alert-danger">
                        {{error[0]}}
                    </div>
                    <input type="text" name="name" class="form-control" placeholder="Name" data-ng-model="transaction. Name" required autofocus>
                    <div>
                        <span class="error" data-ng-show="transactionForm.name.$error.required && submitted">Please enter Name</span>
                    </div>
                    <input type="text" name="type" class="form-control" placeholder="Type" data-ng-model="transaction. Type" required>
                    <div>
                        <span class="error" data-ng-show="transactionForm.type.$error.required && submitted">Please enter Type</span>
                    </div>
                    <! --<input type="text" readonly name="number" class="form-control" placeholder="Number" data-ng-model="transaction. Number">
                    <input type="checkbox" data-ng-model="transaction. IsFinalized" /> <label>Finalize</label>-->

                    <table>
                        <tr>
                            <th>Account</th>
                            <th>Debit</th>
                            <th>Credit</th>
                            <th>&nbsp;</th>
                        </tr>
                        <tr data-ng-form="entryForm" data-ng-repeat="entry in transaction. Entries track by $index">
                            <td>
                                <input required name="accountId" data-ng-model="entry. AccountId" class="form-control" />
                                <span class="error" data-ng-show="entryForm.accountId.$error.required && submitted">Please select an account</span>
                            </td>
                            <td>
                                <input type="text" name="debit" data-ng-required="!entry. CreditAmount" class="form-control" placeholder="Debit" data-ng-model="entry. DebitAmount">
                                <span class="error" data-ng-show="entryForm.debit.$error.required && submitted">Debit is required</span>
                            </td>
                            <td>
                                <input type="text" data-ng-focus="checkAddRow($index)" name="credit" data-ng-required="!entry. DebitAmount" class="form-control" placeholder="Credit" data-ng-model="entry. CreditAmount">
                                <span class="error" data-ng-show="entryForm.credit.$error.required && submitted">Credit is required</span>
                            </td>
                            <td><button data-ng-show="transaction. Entries.length>2" class="btn btn-md btn-info " type="button" data-ng-click="deleteRow($index)">delete</button></td>

                        </tr>
                        <tr>
                            <td>Total</td>
                            <td><input readonly name="totalDebit" type="text" class="form-control" placeholder="Total Debit" data-ng-value="totalDebit()"></td>
                            <td><input readonly name="totalCredit" compare-to="totalDebit" type="text" class="form-control" placeholder="Total Credit" data-ng-value="totalCredit()"></td>
                        </tr>
                        <tr>
                            <td></td>
                            <td><b>Difference</b></td>
                            <td>
                                <input name="difference" readonly type="text" class="form-control" data-ng-value="difference()">
                                <! --<span class="error" data-ng-show="submitted && ! differencezero">Difference should be 0</span>-->
                            </td>
                        </tr>
                    </table><br />
                    <button class="btn btn-md btn-info" type="submit">Create</button>
                    <button class="btn btn-md btn-info" data-ng-show="transaction. Entries.length<15" type="button" data-ng-click="addRow()">Add Row</button>
                    <div data-ng-hide="message == ''" class="alert alert-danger">
                        {{message}}
                    </div>
                </div>
                <div class="col-md-4">

                </div>
                <div class="col-md-2">
                    &nbsp;
                </div>
            </div>
        </form>
        <style type="text/css">
            .error {
                color: red;
            }
        </style>

        <pre>{{transactionForm.entryForm|json}}</pre>
    </div>

I have the requirement that when focus is on Credit input of last entry the new entry should automatically added to the UI.  I do it by using addRow and checkAddRow method on my controller.  these methods are as follows 
$scope.checkAddRow = function (index) {
                if (index == $scope.transaction.Entries.length - 1) {
                    $scope.addRow();
                }
            }

            $scope.addRow = function () {
                entry = {
                    EntryTime: '',
                    DebitAmount: '',
                    CreditAmount: '',
                    AccountId: ''
                };
                $scope.transaction. Entries.push(entry);
                console.log($scope.transactionForm);
            }

            $scope.deleteRow = function (index) {
                $scope.transaction. Entries.splice(index, 1);
                console.log($scope.transactionForm);
            }

Again this part is just fine and works well.  But I have another requirement that says that if last entry is not used it should not cause the form to invalidate.  It should rather be removed from transaction. Entries collection and rest of the data should be saved normally.  To achieve this, I have create function defined on $scope that looks like following
$scope.create = function () {
                $scope.submitted = true;
                if ($scope.transactionForm.entryForm && $scope.transactionForm.entryForm.$invalid && $scope.transactionForm.entryForm.$pristine) {

                    $timeout(function () {
                        $scope.deleteRow($scope.transaction. Entries.length - 1);
                    });

                    $timeout(function () {
                        console.log('From time out', $scope.transactionForm.$valid);
                        console.log($scope.transactionForm.$valid);
                        if (! $scope.transactionForm.$valid) return;

                        alert('data saved!'); 
                        console.log($scope.transactionForm);
                        //$scope.transactionForm.name.focus();
                    }, 200);

                }
                else {
                    if ($scope.transactionForm.$valid) {
                        alert('data saved 2');
                    }
                }

            }

You can see that what create function is doing.  It is checking if entryForm (ng-form) is present in the main form (transactionForm) then it checks if entryForm is $invalid and $pristine if all these flags are true then, I delete the last entry from $scope.transaction. Entries and save the data (currently an alert to show data is saved) after $timeout.  If I don't use timeout then the form is invalid so I have to wait for 200ms before I check the forms $valid flag after removing last row.  But to my surprise when I remove last row from create function, there is no entryForm attached to the outer transactionForm.  On the other hand If I delete entries using delete buttons present on UI, the entryForm is present inside the main transactionForm.  Can anyone explain why is that.  I have added <pre>{{transactionForm|json}}</pre> at the end to see when it is and when it is not available on main form.  I have created a plunk to show what I mean.  just add some data in two input fields of the master portion, enter some data in accountid field of both entries, when you reach the Credit input of second (last) entry, a new entry will be automatically added.  Ignore that row and just push create button.  The last entry will be removed and data will save but the entryForm will not be there anymore.  I am not sure what I am doing wrong. 

A:

So, a problem here is that your definition of whether the form is valid or not depends on the state of the last row. 
The last row could be of the following variety:

row fetched from the backend, but not new --> should only invalidate if not valid
row is new and $pristine --> should not invalidate
row is new, but $dirty (and still last) --> should only invalidate if not valid

You are trying to remove the last row and then re-evaluate the form for validity. 
Approach it the other way - don't let the last row invalidate the form if it's in $pristine state:
Here's a simplified example:
<form name="transactionForm" ng-submit="submit()" novalidate>
  <table>    
    <tr ng-form="entryForm" ng-repeat="transaction in transactions">

      <td><input ng-model="transaction.account" 
                 ng-required="transaction ! == newLastEntry || entryForm.$dirty"></td>

      <td><input ng-model="transaction.amount" 
                 ng-required="transaction ! == newLastEntry || entryForm.$dirty"
                 ng-focus="addEntryIfLast($last)" type="number"></td>
    </tr>
  </table>
</form>

Note $scope.newLastEntry here.  It is set to the new empty (and last) entry.  This happens when you add a new empty row:
function addEmptyEntry(){
  $scope.newLastEntry = {};
  $scope.transactions.push($scope.newLastEntry);
}

And so, ng-required is applied only if row is NOT new last OR otherwise $dirty. 
Then, on submit, you can remove the last entry if it's in $pristine state and indeed the new last (as opposed to whatever existed before):
$scope.submit = function(){
  var itemsToSubmit = angular.copy($scope.transactions);

  if ($scope.transactionForm.$invalid) return;

  if ($scope.transactionForm.entryForm && 
      $scope.transactionForm.entryForm.$pristine && 
      $scope.transactions[$scope.transactions.length - 1] === $scope.newLastEntry) {

    itemsToSubmit.splice(itemsToSubmit.length - 1);
  }
  console.log(JSON.stringify(itemsToSubmit));
};

plunker

