How exactly are the $scope, $element and $attrs variables related, if at all?

时间:2016-07-11 19:38:17

标签: javascript angularjs angularjs-directive

I wrote a custom angular-js directive that asks for user confirmation when navigating away from forms that are half-filled and unsaved.

It works perfectly well but I'm not sure I understand what I'm doing.

The code looks like so:

HTML:

<input type="text" name="username" form-confirmation/>

app.js:

angular.module('myModule').directive('formConfirmation', formConfirm) 

function formConfirm() {
    return {
        restrict: 'A',
        link: function ($scope, $element, $attrs) {

            function conf(event) {

                if ($scope[$element.attr('name')].$dirty) {
                    if (confirm("You have unsaved changes! Are you sure you wish to leave this page?") !== true) {
                        event.preventDefault();
                    }
                }
            };

            $scope.$on('$locationChangeStart', conf);
        }
    }
}

My questions:

1) I tried first using if($element.$dirty) but this didn't work. How is $element different from $scope[$element.attr('name')] ?

2) What is the relationship between $element, $attrs, and $scope?

3) Where did $element's attr method come from?

1 个答案:

答案 0 :(得分:3)

They are related by the element that existed in the DOM and caused AngularJS to execute a compile operation on that element because of the presence of the directive (in this case form-confirmation).

All of these items's definitions are easily found in the directive documentation under Creating a Directive that Manipulates the DOM for the link function:

  • scope is an Angular scope object.
  • element is the jqLite-wrapped element that this directive matches.
  • attrs is a hash object with key-value pairs of normalized attribute names and their corresponding attribute values.
  • controller is the directive's required controller instance(s) or its own controller (if any). The exact value depends on the directive's require property.
  • transcludeFn is a transclude linking function pre-bound to the correct transclusion scope.

To break your questions down further:

  1. I tried first using if($element.$dirty) but this didn't work. How is $element different from $scope[$element.attr('name')] ? You are indexing a property on the $scope object based off of the presence of a specific attribute living on the $element.

  2. What is the relationship between $element, $attrs, and $scope? They are related via the compiled DOM element that contained your directive.

  3. Where did $element's attr method come from? Since $element is a jqLite wrapper for the DOM element, it is simply exposing the attributes that exist on the actual DOM note as the attr property.

I highly recommend that you thoroughly read and digest the directive documentation I linked above. It contains a wealth of knowledge that will help you understand how directives work, which is a core piece of AngularJS.