Let's say I want to write HTML like:
<div my-directive my-start="topModel.start" my-end="topModel.end">
my-directive
has a template that invokes other directives with ngModel
, like so:
<div>
<input ng-model="myStart" />
<input ng-model="myEnd" />
</div>
I would like the inner inputs to transparently update topModel
. It doesn't work this way, because there's no dot in the ng-model
attribute and the value is set in local scope.
The only way I found so far is to watch both models in my-directive
and translate, but it's a horrible abomination.
restrict: 'A',
scope: {
myStart: '=',
myEnd: '='
},
link: function(scope, el, attrs) {
scope.model = { start: scope.myStart, end: scope.myEnd };
scope.$watch("model.start", function(n) {
scope.myStart = n;
});
scope.$watch("model.end", function(n) {
scope.myEnd = n;
});
scope.$watch("myStart", function(n) {
scope.model.start = n;
});
scope.$watch("myEnd", function(n) {
scope.model.end = n;
});
}
How can I pass the bindings through my-directive
to the inner directives without all this manual synchronization?
EDIT : See plunker at http://plnkr.co/edit/ppzVd7?p=preview - this one actually works
EDIT2 : See another at http://plnkr.co/edit/Nccpqn?p=preview - this one shows how "direct access" without dot doesn't work, and with dot and $watches
does.
When you define the scope
property as you do on your directive, you will automatically get two properties, scope.myStart
and scope.myEnd
, with a bidirectional binding to topModel
. When you map them over to scope.model
you break that binding.
Here is a working example:
module.directive('myDirective', function () {
return {
scope: {
myStart: '=',
myEnd: '='
},
template: '<p><label>Start: <input type="text" ng-model="myStart" /></label></p>' +
'<p><label>End: <input type="text" ng-model="myEnd" /></label></p>',
link: function (scope, element, attrs) {
scope.$watch('myStart', function (val, old) {
console.log('Start changed from', old, 'to', val);
});
scope.$watch('myEnd', function (val, old) {
console.log('End changed from', old, 'to', val);
});
}
};
});
With your 2nd example I finally understood your problem, though I still don't think it's comming from breaking the dot-rule . You're simply mixing scopes / model binding (see $parent.myStart
).
Try:
(function (app, ng) {
'use strict';
app.controller('MyCtrl', ['$scope', function($scope) {
$scope.topModel = {
start: 'Initial Start',
end: 'Initial end'
};
}]);
app.directive('myDirective', function(){
return {
scope: { myStart: '=', myEnd: '=' },
template: '<div>\
<p>Start: <span special-editor-a ng-model="$parent.myStart"></span></p>\
<p>End: <span special-editor-b ng-model="myEnd"></span></p>\
</div>'
}
});
// with replace
app.directive('specialEditorA', function(){
return {
scope: true,
require: 'ngModel',
replace: true,
template: '<input type="text" />'
}
});
// without replace
app.directive('specialEditorB', function(){
return {
scope: { m: '=ngModel' },
require: 'ngModel',
template: '<input type="text" ng-model="m" />'
}
});
}(angular.module('app', []), angular));
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.