Где на самом деле добавляется «обязательный» в DOM? - PullRequest
0 голосов
/ 10 мая 2018

Я пытаюсь понять, как angularjs изменяет DOM, особенно в отношении директивы ng-required. Требуемая ng директива ( от GitHub ):

var requiredDirective = function() {
  return {
    restrict: 'A',
    require: '?ngModel',
    link: function(scope, elm, attr, ctrl) {
      if (!ctrl) return;
      attr.required = true; // force truthy in case we are on non input element

      ctrl.$validators.required = function(modelValue, viewValue) {
        return !attr.required || !ctrl.$isEmpty(viewValue);
      };

      attr.$observe('required', function() {
        ctrl.$validate();
      });
    }
  };
};

Я поместил точки останова в функции с помощью отладчика Chrome, и, насколько я могу судить, этот код фактически не изменяет требуемое значение в DOM, но я вижу, что required="required" добавляется и удаляется из ввода элемент. Где в исходном коде angularjs происходит реальная модификация DOM?

Простая форма теста:

        <form>
          <label>Test Select</label>
          <select ng-model="testSelect" ng-required="testIsRequired">
            <option>val 1</option>
            <option>val 2</option>
          </select>
          <label>Required
            <input type="checkbox" ng-model="testIsRequired" />
          </label>

          <label>Output</label>
          <p>
            Test is required:  {{testIsRequired}}
          </p>
          <p>
            Select Value: {{testSelect}}
          </p>
        </form>

1 Ответ

0 голосов
/ 10 мая 2018

Мне наконец удалось получить точку останова в нужном месте.AngularJS устанавливает функцию ссылки по умолчанию для атрибутов «логический» («обязательный», «отключенный» и т. Д.), За исключением атрибута «множественный».

Наблюдаются логические атрибуты, а $set метод attr используется для изменения DOM.

Похоже, что фактический requiredDirective в вопросе имеет дело только с обновлением проверки, когда значение ng-обязательное изменяется.

Соответствующий код (снова от GitHub ):

var ngAttributeAliasDirectives = {};

// boolean attrs are evaluated
forEach(BOOLEAN_ATTR, function(propName, attrName) {
  // binding to multiple is not supported
  if (propName === 'multiple') return;

  function defaultLinkFn(scope, element, attr) {
    scope.$watch(attr[normalized], function ngBooleanAttrWatchAction(value) {
      attr.$set(attrName, !!value);
    });
  }

  var normalized = directiveNormalize('ng-' + attrName);
  var linkFn = defaultLinkFn;

  if (propName === 'checked') {
    linkFn = function(scope, element, attr) {
      // ensuring ngChecked doesn't interfere with ngModel when both are set on the same input
      if (attr.ngModel !== attr[normalized]) {
        defaultLinkFn(scope, element, attr);
      }
    };
  }

  ngAttributeAliasDirectives[normalized] = function() {
    return {
      restrict: 'A',
      priority: 100,
      link: linkFn
    };
  };
});
...