AngularJS: как включить и изолировать и родительскую область?

У меня есть шаблон, в котором многие типы элементов "редактируются". Это означает, что у меня есть множество шаблонов (по одному для каждого редактируемого типа элемента), которые должны иметь уникальные поля, но общие функции (редактирование, сохранение, отмена редактирования, удаление и т. д.). Эти общие функции приводят к большому количеству повторений на контроллерах: save, edit, cancel и т. д., а также к очень повторяющейся обработке ошибок.

Один из способов, который я рассматривал для решения этой проблемы, заключался в том, чтобы каждый контроллер «украшал» себя (используя службу), но это также приводило к беспорядку.

Я предпочитаю директиву, скажем, «редактируемую»:

<form name="editGroup" editable>
   <div ng-show="editMode">
    <!-- lots of fields, e.g. -->
    <input type="text" ng-model="name"></input>
    <span ng-show="editGroup.name.$error.required">The name is required</span>

    <button type="submit" ng-click="save()">Save</button>
    <button ng-click="cancel">Cancel</button>
   </div>
   <div ng-show="!editMode">
    <!-- lots of text, e.g. -->
    <span>{{name}}</span>

    <button ng-click="edit()">Edit</button>
    <button ng-click="delete()">Delete</button>
   </div>
</form>

Проблема в том, что все модели поступают из области controller, поскольку они уникальны для этого шаблона, в то время как повторяющиеся элементы области, такие как функции save() cancel() edit() delete(), поступают из области действия директивы изолировать.

Я, ну, смешиваю прицелы, и, конечно же, я не могу знать заранее, какие предметы должны быть доступны. Итак, если я переведу с:

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

Я делаю что-то неправильно здесь; как лучше (чище?) сделать это?


person deitch    schedule 04.01.2015    source источник
comment
Да, хорошая мысль. И область охвата является дочерней областью. А если изолировать?   -  person deitch    schedule 04.01.2015
comment
Я ошибся, моя скрипка не создавала новую область видимости, она использовала ту же самую. Я обновил скрипку, и, как вы можете видеть, даже несмотря на то, что она находится в дочерней области, вы все равно можете получить доступ к методам из html в директиве. В изолированной области вы можете объявить методы в директиве как $scope.$parent.$save = function... обновленную скрипту, чтобы отразить как унаследованную, так и изолированную область действия   -  person Rei Mavronicolas    schedule 04.01.2015
comment
Я понял. Мне удалось сделать что-то подобное, но без игры с родительской областью.   -  person deitch    schedule 04.01.2015


Ответы (1)


Мне удалось выяснить это, уклонившись от ng-transclude и сделав собственное включение в функцию ссылки.

Ниже приведен эквивалент обычного ng-transclude:

link: function (scope,element,attrs,ctrlr,transclude) {
   var sc = scope.$parent.$new();
   transclude(sc,function(clone,scope) {
      element.append(clone); // or however else you want to manipulate the DOM
   });
}

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

link: function (scope,element,attrs,ctrlr,transclude) {
   var sc = scope.$parent.$new();
   sc.editMode = false;
   sc.save = function() {
   };
   sc.edit = function () {
     sc.editMode = true;
   };
   // etc.
   transclude(sc,function(clone,scope) {
      element.append(clone); // or however else you want to manipulate the DOM
   });
}

Лучшее из обоих миров!

person deitch    schedule 04.01.2015
comment
Можете ли вы показать полный код здесь или предоставить рабочую демонстрацию? - person Karl Horky; 13.01.2016
comment
Конечно. Вот рабочий jsfiddle. Это грубо и просто, но это работает. - person deitch; 13.01.2016
comment
Спасибо за это! Я экспериментировал с изолированными областями и связанными контроллерами и обнаружил, что ваше решение работает и там. Демо здесь: jsfiddle.net/karlhorky/s8pynxtf - person Karl Horky; 14.01.2016