2014-09-03 2 views
0

Я на самом деле назвать директивные функции из контроллеров, как это:

function myControllerFunction = function() { 
    $scope.highlight(); 
} 

highlight(), будучи функцией в директиве.

Что делать, если у меня было две разные директивы, каждая из которых имеет свою собственную функцию highlight()?

Есть ли способ получить фактическую директиву объект, вместо доступа к директивной функции непосредственно через $ scope?

Я предпочел бы быть четко о директиве я хочу использовать, например:

function myControllerFunction = function() { 
    $scope.myDirective.highlight(); 
} 

Возможно ли это?

Если вы хотите знать, почему я хочу контроллер говорить с директивой, вот пример:

Мой контроллер получает булавку аутентификации от пользователя и отправляет его на службу. Служба возвращает значение true, если вывод действителен, иначе false.

В моей функции контроллера я проверяю логическое возвращаемое значение. Если это правда, я называю директивную функцию, называемую highlight, которая просто выделяет div в зеленом, если это правда, иначе я называю это, чтобы выделить его красным цветом.

Вот моя функция контроллера:

$scope.keypadEnter = function() { 
    userService.isCodeValid($scope.code).then(function (result) 
    { 
     if (JSON.parse(result.data)) { 
      $scope.highlight("lime").then(function() { 
       $scope.code = ""; 
       $location.path('/clockin'); 
      }); 
     } 
     else 
     { 
      $scope.highlight("red").then(function() { 
       $scope.resetDisplay(); 
       $scope.code = ""; 
      }); 
     } 
    }); 
}; 

А вот изюминка функция моей директивы:

... 
link: function ($scope, $element, $attrs) { 
    $scope.highlight = function (color) { 
     var deferred = $q.defer(); 

     $element.effect("highlight", { color: color }, 500); 

     $element.find("span").css('color', '#000') 
      .animate({ opacity: 0 }, 500, function() { 
       $element.find("span").css('opacity', 1).css('color', '#fff') 
      }); 

     $timeout(deferred.resolve, 500); 

     return deferred.promise; 
    } 
... 

На основе ваших предложений, я изменил свою директиву код, чтобы наблюдать за переменную $scope.color , например:

angular.module('clockin').directive('grDisplay', function ($q, $timeout) { 
    return { 
     restrict: 'A', 
     link: function ($scope, $element, $attrs) { 

      $attrs.observe('color', function (color) { 
       var deferred = $q.defer(); 

       $element.effect("highlight", { color: color }, 500); 

       $element.find("span").css('color', '#000') 
        .animate({ opacity: 0 }, 500, function() { 
         $element.find("span").css('opacity', 1).css('color', '#fff') 
        }); 

       $timeout(deferred.resolve, 500); 

       return deferred.promise; 
      }); 
     } 
    } 
}); 

И вот мой код просмотра:

<div data-gr-display ng-attr-color="{{ color }}" class="display"><span>{{code}}</span></div> 

Но я получаю эту ошибку:

TypeError: object doesn't support this property or method « observe » 
    at link (http://localhost:18000/App/clockin/keypad/display-directive.js:6:13) 
    at nodeLinkFn (http://localhost:18000/Scripts/angular.js:6692:13) 
... 
+1

Вместо того, чтобы вызывать явно функцию от контроллера, не будет он будет менее запутанным, определяя объект области явно в функции ссылок каждой директивы? то есть $ scope.highlightA = и т. д.? а затем вызов $ scope.highlightA или B? – alou

+0

Это хорошая идея. Благодаря ! Единственное, так как я прочитал ответ Adlen ниже, я не уверен, что я делаю все правильно (вызывая директиву из метода контроллера). Есть ли лучший способ сделать эту работу? – 2014-09-03 14:00:44

+0

Обычно это работа службы, вводя ее в контроллер и используя ее методы или объекты данных, но если это сработает для вас, я думаю, это нормально (это не проблема, пока не будет: P) – alou

ответ

0

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

Кажется, что вы хотите, чтобы ваш контроллер и директивы разговаривали вместе. Для этого вот несколько вариантов.

Вы можете использовать события слушателей, как описано в Creating a Directive that Adds Event Listeners разделе doc, если она основана на браузере событий

Вы можете использовать angular events транслировать события.

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

Редактировать основанный на вопрос редактирования:

Если вам нужно только изменение CSS вы можете использовать атрибут ng-class на вашей директиве, как это:

<my-directive ng-class="{{ status }}"></my-directive> 

Использование attribut вы можете сделать следующее :

link: function ($scope, $element, $attrs) { 
    $attrs.$observe('color', function(color)){ 
     var deferred = $q.defer(); 

     $element.effect("highlight", { color: color }, 500); 

     $element.find("span").css('color', '#000') 
      .animate({ opacity: 0 }, 500, function() { 
       $element.find("span").css('opacity', 1).css('color', '#fff') 
      }); 

     $timeout(deferred.resolve, 500); 

     return deferred.promise; 
} 

А на ваш взгляд:

<my-directive ng-attr-color="{{ color }}"></my-directive> 

Или, если вы хотите систему оповещения вы можете обратиться к Angular UI Bootstrap alert (но я до сих пор не могу понять, почему вам нужны несколько директив для вашей проблемы)

+0

Я отредактировал мой вопрос, чтобы объяснить, почему я это делаю. Благодарю. – 2014-09-03 13:42:33

+0

Вы правы. Мне не нужно больше одной директивы для моей проблемы. Я был просто смущен информацией о контроллере -> директивной связи, в случае, если бы мне пришлось иметь несколько директив для обработки в той же области. Чтобы ответить на ваш последний комментарий, я не уверен, что это только изменение CSS: я использую метод выделения jquery-ui. Это возможно с ng-классом? – 2014-09-03 14:08:56

+0

Не уверен в использовании только CSS для jquery ui, но я предоставил вам пример на основе атрибута –

0

Обычно пути вы общаетесь с директивой по атрибутов, вы обычно не определяете методы в области вашего контроллера на уровне директивы.

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

Возможная реализация может быть:

Контроллер:

$scope.onHightlight = function() { 
    if ($scope.highlightColor === 'lime') { 
     scope.code = ""; 
     $location.path('/clockin'); 
    } else { 
     $scope.resetDisplay(); 
     $scope.code = ""; 
    } 
}); 
$scope.keypadEnter = function() { 
    userService.isCodeValid($scope.code).then(function (result) { 
     if (JSON.parse(result.data)) { 
      $scope.highlightColor = "lime"; 
     } 
     else { 
      $scope.highlightColor = "red"; 
     } 
    }); 
}; 

Директива:

link: function ($scope, $element, $attrs) { 
    var onHightlight = $scope.$eval($attrs['onHightlight']); 

    $scope.$watch($attrs['hightlight'], function(color) { 

     $element.effect("highlight", { color: color }, 500); 

     $element.find("span").css('color', '#000') 
      .animate({ opacity: 0 }, 500, function() { 
       $element.find("span").css('opacity', 1).css('color', '#fff') 
      }); 

     $timeout(onHightlight, 500); 
    } 
.... 
} 

HTML:

<your-directive highlight="highlightColor" onHighlight="onHightlight"></your-directive> 
+0

Спасибо. Можете ли вы привести пример, основанный на коде, который я предоставил для своей директивы? – 2014-09-03 14:13:28

+0

Большое спасибо за ваше время. Наличие директивы, рассматривающей сферу действия, - это путь. – 2014-09-03 15:07:34

Смежные вопросы