在ng-transclude中使用具有原始值的ng-model

时间:2015-05-17 23:40:14

标签: angularjs angularjs-directive angularjs-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无需更改吗?

2 个答案:

答案 0 :(得分:0)

您可以手动转录(而不是使用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);
   });
}

<强> Demo

答案 1 :(得分:-1)

最干净的解决方案是进行一些重构并传递一个对象而不是一个原始值,但如果由于某种原因你不能这样做,那么你就没有选择。

但是,我不推荐任何这些选项

1)从父作用域绑定input,这会阻止在写入时在子作用域上创建新值 - 但请记住,访问父作用域会损害指令的可重用性。 Angular 1.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; }
})

并将其传递给指令。但是,我会再做一些重构。