How does angularjs detect $dirty when no form tag is used?

Viewed 1191

I am using $window.addEventListener('beforeunload'... to detect whether changes have been made to a page, and it is working mostly as expected. I'm also using $transitions.onStart... to detect when the back/forward browser buttons are used. What I don't understand is how this is working, because my HTML template does not have any form tags in it, just inputs inside divs.

I have done research on this and cannot seem to find an answer, other than it is not necessary to use form tags in order to check the dirtiness of inputs. I'm just not sure how this is actually working in the background.

<div class="modal-header bg-primary">
  <button type="button" class="close" data-dismiss="modal">&times;</button>
  <h4 class="modal-title pull-left">New Note</h4>
  <div class="clearfix"></div>
</div>
<div class="modal-body">
  <input type="textfield" ng-model="detailVM.newNoteContent">
  <button ng-click="detailVM.addNewNote()">
    Save New Note <span class="fa fa-check"></span>
  </button>
</div>

Here is my HTML code.

        // For page reloads and attempts to leave the site
        $window.addEventListener('beforeunload', function (e) {
            // Cancel the event
            e.preventDefault();
            // Chrome requires returnValue to be set
            e.returnValue = '';
        });

        // For when a user hits the back button 
        $transitions.onStart({}, function ($transition)
        {
            var answer = confirm("Are you sure you want to leave this page? Changes you made may not be saved.")
            if (!answer) {
                $transition.abort();
                return false;
            }
            return true;
        });

And here is what I have in the controller.

When I enter data into the inputs and then attempt to reload, close, or click the back button, these show the message, "Are you sure you want to leave this page?" But how is it detecting that the inputs are dirty?

1 Answers

ng-model doesn't need to be in a form for it's validators to work.

From the AngularJS docs:

The ngModel directive binds an input,select, textarea (or custom form control) to a property on the scope using NgModelController, which is created and exposed by this directive.

ngModel is responsible for:

  • Binding the view into the model, which other directives such as input, textarea or select require.
  • Providing validation behavior (i.e. required, number, email, url).
  • Keeping the state of the control (valid/invalid, dirty/pristine, touched/untouched, validation errors).
  • Setting related css classes on the element (ng-valid, ng-invalid, ng-dirty, ng-pristine, ng-touched, ng-untouched, ng-empty, ng-not-empty) including animations.
  • Registering the control with its parent form.

— AngularJS ng-model Directive API Reference

If the form is present, ngModelController will register it's controls to the form. This gives you a nice container for tracking the state of an entire set of inputs/controls.

Related