AngularJS : How to transclude and have both isolate scope and parent scope?

倖福魔咒の 提交于 2019-12-07 23:59:57

问题


I have a pattern wherein many item types are "editable". This means that I have lots of templates (one for each editable item type) that expect to have unique fields, but common functions (edit, save, cancel edit, delete, etc.). These common functions lead to lots of repetition on controllers: save, edit, cancel, etc., and very repetitive error-handling.

One way I looked at of dealing with this was to have each controller "decorate" itself (using a service), but it got messy as well.

I prefer a directive, say, 'editable':

<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>

The problem is that all of the models come from the controller scope, since they are unique to this template, while the repetitive scope items, like the functions save() cancel() edit() delete() all come from the directive isolate scope.

I am, well, mixing scopes, and of course I have no way of knowing in advance what items need to be available. So if I transclude with:

  • isolate scope: I lose access to the controller models in the transcluded element, as well as the form for validations
  • controller scope (default): I lose access to the added on functions from the directive, which was the point of the directive in the first place!

I am doing something wrong here; what is the better (cleaner?) way to do this?


回答1:


I managed to figure it out by shying away from ng-transclude and doing my own transclusion in the link function.

The following is the equivalent of the normal 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
   });
}

By adding the functions directly onto the transclude child scope, I was able to have everything work, without messing with the parent scope, which I really didn't want to do.

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
   });
}

Best of both worlds!



来源:https://stackoverflow.com/questions/27765924/angularjs-how-to-transclude-and-have-both-isolate-scope-and-parent-scope

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!