在 ng-transclude 中使用带有原始值的 ng-model
Use ng-model with a primitive value inside ng-transclude
在遗留项目中,我想创建一个使用 transclude 的新指令。
指令代码的精简版本是:
app.directive('controlWrap', function() {
return {
restrict: 'E',
transclude: true,
scope: { label: "@" },
templateUrl: "control-wrap-template.html"
}
})
模板是:
<div>
<label>{{label}}</label>
<div>
<ng-transclude></ng-transclude>
</div>
</div>
这个指令是这样使用的
<control-wrap label="Just a example">
<input type="text" ng-model="input" />
</control-wrap>
Test: {{input}}
我知道 解决方法 是使用作用域中的对象而不是原始值 (ng-model inside ng-transclude)。但这对我来说不是选择。这是一个丑陋的、编码不佳的遗留代码,直接依赖于作用域上的那些属性。
我可以在指令中做些什么来使 html 不加改变地工作吗?
最干净的解决方案是进行一些重构并传递一个对象而不是原始值,但如果由于某种原因您不能这样做,您也不是没有选择。
但是,我不推荐这些选项中的任何一个
1) 从父作用域绑定 input
,这样可以防止在写入时在子作用域上创建新值 - 但请记住,访问父作用域会损害指令的可重用性。
Angular1.2:
<input type="text" ng-model="$parent.input" />
Angular 1.3:
<input type="text" ng-model="$parent.$parent.input" />
(区别是因为嵌入作用域的父作用域是 1.3 中的指令作用域)
2) 创建某种包装对象并传递它而不是原始值
$scope.inputWrapper = {};
Object.defineProperty($scope.inputWrapper, 'input', {
get: function() { return $scope.input },
set: function(newValue) { $scope.input = newValue; }
})
并将其传递给指令。但同样,我会做一些重构。
您可以手动嵌入(而不是使用 ng-transclude
)并将您需要的任何范围(在您的情况下为 scope.$parent
)应用于嵌入的内容:
transclude: true,
scope: { label: "@" },
template: '<div>\
<label>{{label}}</label>\
<placeholder></placeholder>\
</div>',
link: function(scope, element, attrs, ctrls, transclude){
transclude(scope.$parent, function(clone){
element.find("placeholder").replaceWith(clone);
});
}
在遗留项目中,我想创建一个使用 transclude 的新指令。
指令代码的精简版本是:
app.directive('controlWrap', function() {
return {
restrict: 'E',
transclude: true,
scope: { label: "@" },
templateUrl: "control-wrap-template.html"
}
})
模板是:
<div>
<label>{{label}}</label>
<div>
<ng-transclude></ng-transclude>
</div>
</div>
这个指令是这样使用的
<control-wrap label="Just a example">
<input type="text" ng-model="input" />
</control-wrap>
Test: {{input}}
我知道 解决方法 是使用作用域中的对象而不是原始值 (ng-model inside ng-transclude)。但这对我来说不是选择。这是一个丑陋的、编码不佳的遗留代码,直接依赖于作用域上的那些属性。
我可以在指令中做些什么来使 html 不加改变地工作吗?
最干净的解决方案是进行一些重构并传递一个对象而不是原始值,但如果由于某种原因您不能这样做,您也不是没有选择。
但是,我不推荐这些选项中的任何一个
1) 从父作用域绑定 input
,这样可以防止在写入时在子作用域上创建新值 - 但请记住,访问父作用域会损害指令的可重用性。
Angular1.2:
<input type="text" ng-model="$parent.input" />
Angular 1.3:
<input type="text" ng-model="$parent.$parent.input" />
(区别是因为嵌入作用域的父作用域是 1.3 中的指令作用域)
2) 创建某种包装对象并传递它而不是原始值
$scope.inputWrapper = {};
Object.defineProperty($scope.inputWrapper, 'input', {
get: function() { return $scope.input },
set: function(newValue) { $scope.input = newValue; }
})
并将其传递给指令。但同样,我会做一些重构。
您可以手动嵌入(而不是使用 ng-transclude
)并将您需要的任何范围(在您的情况下为 scope.$parent
)应用于嵌入的内容:
transclude: true,
scope: { label: "@" },
template: '<div>\
<label>{{label}}</label>\
<placeholder></placeholder>\
</div>',
link: function(scope, element, attrs, ctrls, transclude){
transclude(scope.$parent, function(clone){
element.find("placeholder").replaceWith(clone);
});
}