Директива AngularJS: вызов метода из родительской области в шаблоне

#javascript #angularjs #templates #scope #directive

#javascript #angularjs #шаблоны #область #директива

Вопрос:

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

Контроллер:

 controller('profileCtrl', function($scope) {
  $scope.editing = {
    'section1': false,
    'section2': false
  }
  $scope.updateProfile = function() {};
  $scope.cancelProfile = function() {};
});
  

Директива:

 directive('editButton', function() {
  return {
    restrict: 'E',
    templateUrl: 'editbutton.tpl.html',
    scope: {
      editModel: '=ngEdit'
    }
  };
});
  

Шаблон (editbutton.tpl.html ):

 <button
  ng-show="!editModel"
  ng-click="editModel=true"></button>
<button
  ng-show="editModel"
  ng-click="updateProfile(); editModel=false"></button>
<button
  ng-show="editModel"
  ng-click="cancelProfile(); editModel=false"></button>
  

HTML:

 <edit-button ng-edit="editing.section1"></edit-button>
  

Если это непонятно, я хочу, чтобы <edit-button> тег содержал три разные кнопки, каждая из которых взаимодействовала с любым переданным в нее свойством области ng-edit . При нажатии они должны изменить это свойство, а затем вызвать соответствующий метод области.

Как и сейчас, нажатие кнопок корректно изменяет значения $scope.editing , но методы updateProfile и cancelProfile не работают. Возможно, я далек от понимания того, как правильно использовать директивы, но у меня возникли проблемы с поиском примера в Интернете, который помог бы мне выполнить то, что я пытаюсь сделать. Любая помощь была бы оценена.

Ответ №1:

Одним из способов было бы вызвать функции с помощью $parent .

 <button ng-show="editModel" ng-click="$parent.cancelProfile(); editModel=false">b3</button>
  

ДЕМОНСТРАЦИЯ

Другой способ (и, вероятно, лучший способ) — настроить изолированную область действия вашей директивы так, чтобы она содержала ссылки на эти функции контроллера:

 app.directive('editButton', function() {
  return {
    restrict: 'E',
    templateUrl: 'editbutton.tpl.html',
    scope: {
      editModel: '=ngEdit',
      updateProfile: 'amp;',
      cancelProfile: 'amp;'
    }
  };
});
  

Затем вы передаете функции через HTML:

 <edit-button ng-edit="editing.section1" update-profile='updateProfile()' cancel-profile='cancelProfile()'></edit-button>
  

ДЕМОНСТРАЦИЯ

Комментарии:

1. Отлично, спасибо. Я склонен использовать ваш первый пример, поскольку два метода всегда будут одинаковыми для всех директив, и это уменьшит количество посторонних html. Что заставляет вас говорить, что второй способ является «лучшим способом»?

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

3. Подтолкнуло меня в правильном направлении, но что, если я хочу передать аргументы методам, используя ваш второй пример?

4. Передайте свой аргумент в качестве объекта. Что-то вроде этого: update-profile='updateProfile({message: testMessage})' .