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