我试图创建一个指令,将创建一个输入字段与元素相同的ng-model创建指令。
这是我目前想到的:
HTML
<!doctype html>
<html ng-app="plunker" >
<head>
<meta charset="utf-8">
<title>AngularJS Plunker</title>
<link rel="stylesheet" href="style.css">
<script>document.write("<base href=\"" + document.location + "\" />");</script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.0.2/angular.js"></script>
<script src="app.js"></script>
</head>
<body ng-controller="MainCtrl">
This scope value <input ng-model="name">
<my-directive ng-model="name"></my-directive>
</body>
</html>
JavaScript
var app = angular.module('plunker', []);
app.controller('MainCtrl', function($scope) {
$scope.name = "Felipe";
});
app.directive('myDirective', function($compile) {
return {
restrict: 'E',
scope: {
ngModel: '='
},
template: '<div class="some"><label for="{{id}}">{{label}}</label>' +
'<input id="{{id}}" ng-model="value"></div>',
replace: true,
require: 'ngModel',
link: function($scope, elem, attr, ctrl) {
$scope.label = attr.ngModel;
$scope.id = attr.ngModel;
console.debug(attr.ngModel);
console.debug($scope.$parent.$eval(attr.ngModel));
var textField = $('input', elem).
attr('ng-model', attr.ngModel).
val($scope.$parent.$eval(attr.ngModel));
$compile(textField)($scope.$parent);
}
};
});
然而,我不相信这是处理此场景的正确方法,并且有一个错误,即我的控件没有使用ng-model目标字段的值进行初始化。
下面是上面代码的一个Plunker: http://plnkr.co/edit/IvrDbJ
正确的处理方法是什么?
编辑:从模板中删除ng-model="value"后,这似乎工作得很好。但是,我将保留这个问题,因为我想再次确认这是正确的方法。
编辑:这个答案已经过时了。只是提醒一下,以免误导大家。我已经不再使用Angular了,所以我不适合进行改进。
这实际上是很好的逻辑,但你可以把事情简化一点。
指令
var app = angular.module('plunker', []);
app.controller('MainCtrl', function($scope) {
$scope.model = { name: 'World' };
$scope.name = "Felipe";
});
app.directive('myDirective', function($compile) {
return {
restrict: 'AE', //attribute or element
scope: {
myDirectiveVar: '=',
//bindAttr: '='
},
template: '<div class="some">' +
'<input ng-model="myDirectiveVar"></div>',
replace: true,
//require: 'ngModel',
link: function($scope, elem, attr, ctrl) {
console.debug($scope);
//var textField = $('input', elem).attr('ng-model', 'myDirectiveVar');
// $compile(textField)($scope.$parent);
}
};
});
带有指令的Html
<body ng-controller="MainCtrl">
This scope value <input ng-model="name">
<my-directive my-directive-var="name"></my-directive>
</body>
CSS
.some {
border: 1px solid #cacaca;
padding: 10px;
}
你可以在这个Plunker上看到它的作用。
以下是我的看法:
我理解为什么你想使用“ng-model”,但在你的情况下,这是没有必要的。Ng-model是将现有的HTML元素与作用域中的值链接起来。因为你是在自己创建一个指令,你是在创建一个“new”html元素,所以你不需要ng-model。
正如Mark在他的评论中提到的,你没有理由不能使用ng-model,只是为了保持惯例。
通过显式地在你的指令中创建一个作用域(一个“隔离的”作用域),指令的作用域不能访问父作用域中的“name”变量(这就是为什么,我认为,你想要使用ng-model)。
我从你的指令中删除了ngModel,并将其替换为一个自定义名称,你可以更改为任何名称。
使它仍然有效的是作用域中的'='符号。签出'scope'标题下的文档。
一般来说,你的指令应该使用隔离作用域(你做对了),如果你想让你的指令中的值总是映射到父作用域中的值,就应该使用'='类型作用域。
编辑:这个答案已经过时了。只是提醒一下,以免误导大家。我已经不再使用Angular了,所以我不适合进行改进。
这实际上是很好的逻辑,但你可以把事情简化一点。
指令
var app = angular.module('plunker', []);
app.controller('MainCtrl', function($scope) {
$scope.model = { name: 'World' };
$scope.name = "Felipe";
});
app.directive('myDirective', function($compile) {
return {
restrict: 'AE', //attribute or element
scope: {
myDirectiveVar: '=',
//bindAttr: '='
},
template: '<div class="some">' +
'<input ng-model="myDirectiveVar"></div>',
replace: true,
//require: 'ngModel',
link: function($scope, elem, attr, ctrl) {
console.debug($scope);
//var textField = $('input', elem).attr('ng-model', 'myDirectiveVar');
// $compile(textField)($scope.$parent);
}
};
});
带有指令的Html
<body ng-controller="MainCtrl">
This scope value <input ng-model="name">
<my-directive my-directive-var="name"></my-directive>
</body>
CSS
.some {
border: 1px solid #cacaca;
padding: 10px;
}
你可以在这个Plunker上看到它的作用。
以下是我的看法:
我理解为什么你想使用“ng-model”,但在你的情况下,这是没有必要的。Ng-model是将现有的HTML元素与作用域中的值链接起来。因为你是在自己创建一个指令,你是在创建一个“new”html元素,所以你不需要ng-model。
正如Mark在他的评论中提到的,你没有理由不能使用ng-model,只是为了保持惯例。
通过显式地在你的指令中创建一个作用域(一个“隔离的”作用域),指令的作用域不能访问父作用域中的“name”变量(这就是为什么,我认为,你想要使用ng-model)。
我从你的指令中删除了ngModel,并将其替换为一个自定义名称,你可以更改为任何名称。
使它仍然有效的是作用域中的'='符号。签出'scope'标题下的文档。
一般来说,你的指令应该使用隔离作用域(你做对了),如果你想让你的指令中的值总是映射到父作用域中的值,就应该使用'='类型作用域。