Angular自定义指令 - 双向绑定,始终将属性设置为true或false

时间:2015-04-14 18:29:29

标签: javascript angularjs angularjs-directive angularjs-scope

我正在为菜单中的幻灯片创建一个自定义Angular指令,该指令需要观察几个属性,其中一个属性需要双向绑定到主控制器范围(有时)。但是,有时开发人员不会添加该属性,因此需要自动添加该属性并将其设置为默认值(false)。因此,该指令可以像这样使用。

<slide-menu position="right" is-open="menuIsOpen"></slide-menu>

或者像这样:

<slide-menu></slide-menu>

使用第一种方式时,主控制器可以通过更改布尔值$ scope.menuIsOpen的值来打开和关闭菜单。

如果在不提供is-open属性的情况下使用它,它应该默认为false,显然在内部和子切换指令中使用。

另一个复杂因素是,该属性是否由开发人员提供,它应该存在于DOM中。所以在上面的第二个例子中,指令默认将自己设置为false,并将属性is-open =“false”添加到DOM中?

在DOM中始终要求is-open =“false / true”的原因是菜单实际上是使用使用以下选择器的CSS tansition操作的:

slide-menu[is-active="true"]{
    // Slide the menu in using transforms/transitions
}

这里有一个jsfiddle,显示我已经走了多远。

http://jsfiddle.net/jonhobbs/gEPvE/

显然它不起作用,但它显示了我如何尝试设置默认值以及我如何尝试使用@和&amp;在一次性绑定的隔离范围(菜单位置)和is-open变量的双向绑定表达式。

我显然距离实现我的需要还有很长的路要走,但任何建议都会受到赞赏。

3 个答案:

答案 0 :(得分:1)

您需要将ngTouch添加到模块中。

var app = angular.module('app', ['ngTouch']);

并添加此脚本:

http://ajax.googleapis.com/ajax/libs/angularjs/1.2.1/angular-touch.js

答案 1 :(得分:1)

看看这个小提琴http://jsfiddle.net/gEPvE/38/ 我拿了你开始的那个并更新它,就像你指定的一样。

你可以添加一个双向绑定值可选吗?关于范围定义。

喜欢这个

{
    scope: {
        'isOpen':'=?'
    }
}

现在,is-open属性是可选的。 然后,您可以在指令控制器中设置默认值,就像您已经开始那样。

接下来,为了将DOM属性与范围值同步,您可以使用$ watch。

$scope.$watch('isOpen', function(val) {
    $element.attr('is-open', val);
});

最后,我更改了第二个“幻灯片切换”。包装/转换其元素以添加ng-click处理程序的指令。这主要是为了避免在调用$ scope时出现任何肮脏。$ apply自己。

请告诉我这是否适合您。


修改

在评论中回答你的问题,你可以直接传递一个值,而不必将它绑定到范围,你只需要将值包装在引号中。

例如

<div ng-controller='ctrl'>
  <hello world='imOnScope'></hello>
</div>

假设&#39;你好&#39;是一个范围为&#39; world&#39;:&#39; =?&#39;然后,angular将为父范围分配一个参考&#39; imOnScope&#39;对象指令的$ scope.world成员,允许双向绑定方案。

要直接提供值,您可以执行类似的操作

<div ng-controller="ctrl">
    <hello world="'directValue'"></hello>
</div>

在这种情况下,角度将只分配&#39; directValue&#39;指令的$ scope.world成员。

答案 2 :(得分:0)

  

要求的原因是-ope =&#34; false / true&#34;在任何时候都在DOM中   是菜单实际上使用CSS使用的tansition操作   以下选择器

强制指令属性适合css选择器是个糟糕的主意。正如您所说,它们适用于开发人员。因此,动态地向元素添加一个类。

您似乎在滥用&,设置回调是可以的,但由于您不这样做,因此在当前状态下您最终可以使用 - 方式@充满信心。

我想它可能像this(只是为父范围添加了ngTouch和ng-controller)。


你可以替换

$scope.watch('isOpen', function () {
    $element.toggleClass('opened', $scope.isOpen);
});

$scope.watch('isOpen', function () {
    $attrs.isOpen = !!$scope.isOpen;
});

并获得您要求的行为,这很容易。好的,它现在是布尔值,它反映了范围,您可以使用[is-open=true]选择器。但是猜猜你的绑定会发生什么?破碎。幸运的是,你可以做到

$scope.watch('isOpen', function () {
    $element.attr('is-open', !!$scope.isOpen);
});

代替。瞧,我们欺骗了Angular,因为它并没有照顾jqlite。但是,当指令因任何原因重新编译时,绑定将会发生什么?同样,isOpen的绑定是不存在的&#39; true&#39;或者&#39; false&#39;范围变量。碎。