Как привязать ng-click к пользовательской директиве и вызвать родительскую функцию?

Мы используем Angular 1.4.2, и я пытаюсь получить значение счетчика из директивы с помощью ng-click, передать его функции, а затем передать его родительскому контроллеру. После некоторых усилий он работает в пакете, но, к сожалению, когда я попытался перенести эту функциональность обратно в основной код, я не смог заставить контроллер привязаться к изолированной области.

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

Вот код:

ШАБЛОН:

<!DOCTYPE html>
<html>

  <head>
    <script data-require="angular.js@1.4.2" data-semver="1.4.2" src="https://code.angularjs.org/1.4.2/angular.js"></script>
    <link rel="stylesheet" href="style.css" />
    <script src="script.js"></script>
  </head>

  <body>
    <div id="app" ng-app="app">
    <div ng-controller="mainCtrl">
          <my-directive ctrl-fn="ctrlFn(count = count + 10)"></my-directive> 
        </div>
      </div>
  </body>

</html>

СЦЕНАРИЙ:

var app = angular.module('app', []);
app.controller('mainCtrl', function($scope){
  $scope.count = 0;
  $scope.ctrlFn = function() {
      console.log('In mainCtrl ctrlFn!');
      //$scope.count += 10; Old hardcoded value.
      console.log("count is: " + JSON.stringify($scope.count));
    //Call service here
  };  
});

app.directive('myDirective', function() {
  return {
    restrict: 'E',
    scope: {
      'ctrlFn' : '&'
    },
    template: "<div><button ng-click='ctrlFn()'>Click Here</button></div>",
    link: function(scope, element, attributes) {
      scope.ctrlFn(count);
    }
  };
});

Вот код шаблона, который я пытаюсь изменить в основной базе кода:

<div>
    <div layout="row">
        <results-loader ctrl-fn="ctrlFn(count = count + 10)"></results-loader>
        <md-button class="md-raised md-primary md-button" ng-click="ctrlFn()" flex>Click Me</md-button>
    </div>
</div>

и вот где я использую существующий контроллер в моей директиве в качестве родительского контроллера. Он определен в маршруте, а не в ng-controller, и уже используется для этого представления.

myresultsCtrl.$inject = ['$scope', ' myService'];
        /* @ngInject */
        function myresultsCtrl($scope, myService) {
            $scope.count = 0;
etc...

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

Как я уже говорил, я попытался добавить новый контроллер в шаблон, затем я попытался добавить существующий контроллер в директиву, но ни один из них не сработал. Я вынул шаблон из директивы и попытался поместить ng-click непосредственно в шаблон с помощью ctrl-fn, но я не был уверен, как связать щелчок с вызовом атрибута ctrl-fn директивы с помощью как в шаблоне? Идея здесь состоит в том, чтобы переместить шаблон в его собственный html-файл и ссылаться на него из директивы, как показано в: template: "myFile.html. Я пытаюсь как можно больше использовать этот шаблон, чтобы превратить его в повторно используемый компонент.

Я не много работал с пользовательскими директивами.

Вот прямая ссылка на вантуз.

2 ответа

Решение

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

Я застрял в том, как правильно настроить контроллер для этого варианта использования. Хотя я объявил свой контроллер в модуле и ввел контроллер, поскольку он уже связан с этим представлением, мне нужно было определить контроллер в самой директиве. Как только я сделал все три вместе, все начало работать.

Вот некоторые фрагменты кода:

angular.module('directiveName', [])
        .directive('directiveName', directiveName)
        .controller('injectedCtrl', injectedCtrl)
        etc...

var directive = {
        restrict: 'E',
        scope: {
            'ctrlFn' : '&'
        },
        template: "<div><button ng-click='ctrlFn()'>Click Here</button></div>",
        controller: "injectedCtrl",
        link: function(scope, element, attributes) {
            scope.ctrlFn(); //This will pass to the parent controller: injectedCtrl, where $scope resides.
        }
    }
    return directive;   
}


injectedCtrl.$inject = ['$scope', 'myService'];
    /* @ngInject */
    function injectedCtrl($scope, myService) {
    $scope.ctrlFn = function() {
        //do something
    }
    etc...

HTML-код:

Когда кнопка нажата из директивы, ctrlFn - это ссылка, находящаяся в изолированной области действия моих директив в DDO. Это принимает внешнюю функцию, которая была передана, а именно: ctrlFn(), которая затем может быть вызвана из директивы для вызова родительского контроллера.

<div layout="row">
        <results-loader ctrlFn="ctrlFn()"></results-loader> 
    </div>

Я публикую это, чтобы помочь кому-то еще, у кого может быть этот вариант использования, так как это было нелегко понять.

В статье Dah Wahlins более подробно рассматривается эта тема: Создание пользовательских директив AngularJS, часть 3 - Изоляция области действия и параметров функций, а также то, что помогло уточнить мое мышление.

Я не знаю ваше точное назначение, но переосмыслите вашу архитектуру. Почему вы хотите посчитать значение в директиве? В вашем простом случае было бы лучше посчитать значение в службе или в контроллере, а не в директиве.

Контроллер впрыска в директиве имеет антиангулярную схему. Вы должны переосмыслить свои намерения. Лучше передать номер в директиву, провести там вычисления и отправить свой номер обратно контроллеру. Это будет работать без дополнительного кода, из-за двусторонней привязки данных. Вот ответвление вашего плункера: http://plnkr.co/edit/KpB6bv5tHvXSvhErLcEp?p=preview Основная часть - это определение директивы:<div><span>{{count}}</span><br /><button ng-click='myFunction()'>Calculate</button></div>

Другие вопросы по тегам