我想在angularjs中编写'edit in place'指令.我希望该指令是可重用的,因此我对该指令有以下要求:
我在这个小提琴http://jsfiddle.net/honzajde/ZgNbU/1/中可以看到指令中范围可见性的欺骗行为.
=>当两者都被注释掉时只需将模板添加到指令使得它渲染contact.number即使不使用模板.
我在问游戏的规则是什么?
<div>
<div ng-controller="ContactsCtrl">
<h2>Contacts</h2>
<br />
<ul>
<li ng-repeat="contact in contacts">
<span edit-in-place="" ng-bind="contact.number"></span> |
<span edit-in-place="" >{{contact.name}}</span>
</li>
</ul>
<br />
<p>Here we repeat the contacts to ensure bindings work:</p>
<br />
<ul>
<li ng-repeat="contact in contacts">
{{contact.number}} | {{contact.name}}
</li>
</ul>
</div>
</div>
var app = angular.module( 'myApp', [] );
app.directive( 'editInPlace', function() {
return {
restrict: 'A',
//scope: { contact:"=" },
template: '<span ng-click="edit()" ng-bind="value"></span><input ng-model="value"></input>',
link: function ( $scope, element, attrs ) {
// Let's get a reference to the input element, as we'll want to reference it.
var inputElement = angular.element( element.children()[1] );
// This directive should have a set class so we can style it.
element.addClass( 'edit-in-place' );
// Initially, we're not editing.
$scope.editing = false;
// ng-click handler to activate edit-in-place
$scope.edit = function () {
$scope.editing = true;
// We control display through a class on the directive itself. See the CSS.
element.addClass( 'active' );
// And we must focus the element.
// `angular.element()` provides a chainable array, like jQuery so to access a native DOM function,
// we have to reference the first element in the array.
inputElement[0].focus();
};
// When we leave the input, we're done editing.
inputElement.prop( 'onblur', function() {
$scope.editing = false;
element.removeClass( 'active' );
});
}
};
});
app.controller('ContactsCtrl', function ( $scope ) {
$scope.contacts = [
{ number: '+25480989333', name: 'sharon'},
{ number: '+42079872232', name: 'steve'}
];
});
Run Code Online (Sandbox Code Playgroud)
你正在遇到问题,因为你误用角度.
首先,指令应该是自包含的,但是你要从中提取功能,这使得它不那么普遍并且不太可重复使用.在您的代码中,您在DOM和控制器中具有属于指令的功能.为什么?
其次,你的标记也不清楚,javascript特别希望你想要在所有这些部分串在一起时完成.
第三,在大多数情况下,指令应该有自己的独立范围,这是通过声明一个带有应该绑定的属性的范围对象来完成的.你不应该{{contact.name}}在指令中传递一个表达式(即),因为它会破坏绑定,并且当就地编辑完成时你的联系人不会被更新.正确的方法是通过=范围内的属性建立双向绑定.ng-bind这不是你想要的:那是特定于范围的,所以我们在指令的范围内使用它.正如Valentyn建议的那样,你可以做一些魔术来解决这个问题,但这不是一个好主意,以正确的方式设置它是非常简单的.通过属性执行此操作有什么问题?
这都是糟糕的Ju-ju.
正如我在你关于同一主题的另一个问题中指出的那样,你必须使你的指令自成一体并使用角度而不是反对它.这是我之前给你的小提琴的基于属性的版本,符合你的第一个要求.请让我知道这个实现有什么问题,我们可以谈谈修复它的角度方式.
最后,如果您根据"按钮"提供有关所需内容的更多背景信息,我也会将其纳入小提琴中.
[更新]
有可能使指令按照您的方式工作,但最终会遇到问题(或者现在看起来似乎).角度应用程序(或任何应用程序)中的所有组件应尽可能独立.这不是"规则"或限制; 这是一个"最佳实践".类似地,指令组件之间的通信可以通过控制器进行,但不应该.理想情况下,您根本不应该在控制器中引用DOM - 这就是指令的用途.
如果您的特定目的是可编辑的行,那么这是您的指令.可以使用较大指令使用的较低级别通用编辑就地指令,但仍然存在更高级别的指令.更高级别的指令封装了它们之间的逻辑.然后,这个更高级别的组件将需要联系对象.
最后,不,ng-bind="var"和之间不一定有很大的区别{{var}}.但那不是问题; 这个问题是在那里是发生结合.在您的示例中,值传递给指令而不是双向绑定变量.我的观点是该指令需要访问变量,以便它可以更改它.
简介:您正在以一种非常jQuery风格的方式编写代码.这对于jQuery中的编码很有用,但是在Angular中进行编码时效果不佳.事实上,它会导致许多问题,例如您正在经历的问题.例如,在jQuery中,您可以手动插入DOM元素,声明和处理事件,并在一个代码块中手动绑定变量.在Angular中,关注点清晰分离,大多数绑定都是自动的.在大多数情况下,它导致javascript代码至少比jQuery替代方案小三分之二.这是其中一个案例.
也就是说,我创建了一个Plunker,其中包含一个更复杂的编辑版本以及一个新的更高级别指令,以包含其他功能:http://plnkr.co/edit/LVUIQD?p =预览.
我希望这有帮助.
[更新2]
这些是您新一轮问题的答案.它们可能对你的启发很有帮助,但我已经为你提供了解决问题的"棱角分明的方法".您还会发现我在原始答案和更新中已经解决了这些问题(更广泛的描述).希望这更加明显.
问题: "在指令中注释:模板和范围 - > contact.number和contact.name显示"
我的回复:当您没有指定范围时,该指令继承其父范围.您在父项的上下文中绑定并插入了名称和数字,因此它"有效".但是,因为该指令会改变该值,所以这不是解决它的好方法.它确实应该有自己的范围.
问题: "在指令中填写:范围 - >仅显示contact.number"
我的回复:您将父级的范围属性绑定到"contact.number"指令,因此它将在$ digest循环中放入 - 在处理指令之后.在"contact.name"上,您将其放在指令中,该指令仅在指令代码进行转换时才有效.
问题: "不评论任何内容 - >没有显示任何内容"
我的回复:对.如果指令有自己的范围(并且肯定应该这样),那么必须使用已定义的指令范围属性来传递值,正如我的几个代码示例所示.但是,当我们通过scope在其定义中使用属性明确禁止时,您的代码会尝试使用指令中的父作用域.
简介:虽然第二次更新可能是提供信息的(我希望它是),但它没有回答你的问题下面的问题:我如何正确使用角度组件,以便我使用的范围始终是我认为的是什么?我的第一篇文章和随后的更新,回答了这个问题.
| 归档时间: |
|
| 查看次数: |
6630 次 |
| 最近记录: |