Проверка определенных функций во вложенных директивах

0

При передаче функции в директиву, которая затем передается во вложенную дочернюю директиву, функция всегда считается определенной при проверке в области дочерней директивы, независимо от того, передана она или нет в родительской директиве.

Есть ли лучший способ либо передать указатели на функции, либо проверить, определены ли они при работе с вложенными директивами.

plunker

<body ng-app="myApp">
  <div ng-controller="myController">
    <dir1"></dir1>
  </div>

  <script type="text/ng-template" id="dir1">
    <div>
      <dir2 fun="fun()"></dir2>
    </div>
  </script>
  <script type="text/ng-template" id="dir2">
    <div>{{fun()}}</div>
    <div>{{funDefined()}}</div> <!-- always true-->
  </script>
</body>

var app = angular.module('myApp', []);

app.controller('myController', function($scope) {
  $scope.fun = function() {
    alert("function");
  };
});

app.directive('dir1', function() {
  return {
    scope: {
      fun: '&'
    },
    templateUrl: 'dir1'
  };
});

app.directive('dir2', function() {
  return {
    scope: {
      fun: '&'
    },
    link: function(scope, elem, attrs) {
      scope.funDefined = function() {
        return angular.isDefined(attrs.fun);
      };
    },
    templateUrl: 'dir2'
  };
});
  • 0
    Ну, а определяется, насколько dir2 обеспокоен. Ответственность за правильные аргументы несет вызывающий.
Теги:

3 ответа

0

Лучший способ, который я мог найти, основан на том, что @xersiee прокомментировал в другом ответе. Идея состоит в том, чтобы сделать параметр области необязательным в родительской директиве, а затем использовать angular.isUndefined(scope.$parent.$eval(attribute.myFun)) чтобы проверить, была ли эта функция передана или нет. Это не объясняется в официальной документации... Интересно, почему.

Как отмечали другие люди, это решение далека от идеала, потому что использование области. $ Parent - это анти-шаблон, но опять же, это лучший вариант, который я мог бы найти.

Plunker с этим решением: http://plnkr.co/edit/SUUMae?p=preview

0

Там нет элегантного способа, который я знаю, чтобы получить то, что вы хотите. Как это было упомянуто до этой строки:

angular.isDefined(attrs.fun)

выполняет проверку строки, поэтому возвращает true при каждом атрибуте fun. И в вашем шаблоне директивы dir1 у вас есть <dir2 fun="fun()"></dir2> так что, очевидно, будет определено fun (и это строка). Если вы посмотрите на угловые источники:

case '&':
            // Don't assign Object.prototype method to scope
            parentGet = attrs.hasOwnProperty(attrName) ? $parse(attrs[attrName]) : noop;

            // Don't assign noop to destination if expression is not valid
            if (parentGet === noop && optional) break;

            destination[scopeName] = function(locals) {
              return parentGet(scope, locals);
            };
            break;

вы увидите, что наличие атрибута всегда приведет к некоторой функции, назначенной области ($parse возвращает функцию даже для строки, которая не имеет большого смысла).

Поэтому единственным решением, которое я могу придумать, является выполнение проверки в директиве первого уровня (возможно, поскольку атрибут действительно не определен) и имеют два <dir2> (с атрибутом "без fun) - каждый всегда исключает использование ng-if. Что-то вроде этого. Опять же, я знаю, его уродливое решение.

Одностороннее примечание. Угловой источник также показывает, что свойство scope не будет установлено, если нет атрибута и привязки необязательно (с использованием &?) - тогда вы можете проверить значение scope.fun вместо attrs.fun - некоторые могут показаться более элегантными.

0

Если вы установите отладчик внутри вашего метода scope.funDefined dir2, вы увидите, что attrs.fun равно строке "fun()". Это потому, что вы берете исходную ценность из атрибутов. И поскольку это не пустая строка, она всегда даст вам true.

Здесь обновляется плункер

Ещё вопросы

Сообщество Overcoder
Наверх
Меню