AngularJS自定义指令,如何绑定和接受鼠标事件?

时间:2022-11-26 23:25:04

I require a custom DOM element that accepts mouse clicks and whose state is dependant on the model:-

我需要一个自定义DOM元素,它接受鼠标点击,其状态取决于模型:-

<card ng-repeat="card in cards" x="card.x"
    y="card.y" color="card.color" on-click="test_click('b')">
</card>

I am able to build a custom directive that binds to a controller's scope variables through its DOM attributes and use them to alter its view. I have this working by allowing the directive to inherit its parents scope:

我能够构建一个自定义指令,该指令通过其DOM属性绑定到控制器的范围变量,并使用它们修改其视图。我通过允许指令继承其父母的范围来工作:

app.directive('card', function ($timeout) {
    return {
        restrict:'E',
        link:function (scope, element, attrs) {
            element.addClass('card');

            element.click(function(){
                scope.onClick()
            });

            scope.$watch(attrs.x, function (x) {
                element.css('left', x + 'px');
            });
            scope.$watch(attrs.y, function (y) {
                element.css('top', y + 'px');
            });
            scope.$watch(attrs.color, function (color) {
                element.css('backgroundColor', color);
            });
        }
        /*
        ,scope:{
            x:'=',
            y:'=',
            color:'=',
            onClick: "&"
        }
        */
    };
});

I am able to get a mouse click event to propagate up to the controller by creating an isolated scope and doing some rewiring (by commenting the scope in above).

通过创建一个独立的范围并进行一些重新布线(通过注释上面的范围),我能够获得一个鼠标单击事件传播到控制器。

However, I am unable to get both behaviours working at the same time.

然而,我无法让这两种行为同时发生。

I presume I need to get the x variable bound to the attribute value, which is what I have tried to do. But even by trying every combination of syntax I can think of, I just can't seem to get it working.

我假设我需要将x变量绑定到属性值,这就是我要做的。但是即使我尝试了所有我能想到的语法组合,我还是不能让它工作。

Here is the complete case jsfiddle

这是完整的案例jsfiddle

2 个解决方案

#1


3  

If I understand what you're trying to do, you can use ng-style instead of $watch()es, and ng-click instead of element.click():

如果我理解您的意图,您可以使用ng-style代替$watch()es,使用ng-click代替element.click():

<card ng-repeat="card in cards" ng-click="test_click('b')"
  ng-style="{left: card.x, top: card.y, 'background-color': card.color}" >

Fiddle

小提琴

When we use any of the pre-built Angular directives -- e.g., ngStyle, ngRepeat, ngClass, ngSwitch, ngShow -- and tie them to models, Angular does the watch()ing for us.

当我们使用任何预先构建的角度指示——例如ngStyle、ngRepeat、ngClass、ngSwitch、ngShow——并将它们与模型绑定时,角度为我们做手表()。

(I don't understand why it only works if I include jQuery. I don't see any jQuery-specific methods being called.)

(我不明白为什么只有包含jQuery才能起作用。我没有看到调用任何特定于jquery的方法。

Update: I figured out how to make it work without jQuery -- add 'px' to the ng-style:

更新:我知道了如何让它在没有jQuery的情况下运行——在ng样式中添加“px”:

<card ng-repeat="card in cards" ng-click="test_click('b')
  ng-style="{left: card.x + 'px', top: card.y + 'px', 'background-color': card.color}" ">

Updated fiddle.

更新的小提琴。

I guess jQuery is more forgiving somehow if we leave off the 'px'.

我猜如果我们去掉“px”,jQuery会更宽容。

To the second fiddle, I also added a "move card #1 down 200px" ng-click/hyperlink, to prove that changing the model results in Angular automatically updating the view for us.

其次,我还添加了“移动卡#1向下200px”的ng-click/hyperlink,以证明更改模型会自动地为我们更新视图。

#2


0  

Ahhhhh, I had the correct approach, the watchers had broken though. Clearly I don't fully understand the semantics of $watch, as I am not totally understanding the solution. I only realised it by printing out the scope and detecting the right variables were present in the isolated scope case.

啊啊啊啊,我找到了正确的方法,但看守者已经崩溃了。显然,我没有完全理解$watch的语义,因为我没有完全理解这个解决方案。我只是通过打印范围和检测在隔离范围情况下存在的正确变量来实现它。

anyway, the solution: I changed the $watch calls to:-

不管怎样,解决方案是:我把$watch的电话改成:-

scope.$watch("x", function (x) {
    element.css('left', scope.x + 'px');
});

and this tracked changes to the bound variables

它跟踪了绑定变量的变化

#1


3  

If I understand what you're trying to do, you can use ng-style instead of $watch()es, and ng-click instead of element.click():

如果我理解您的意图,您可以使用ng-style代替$watch()es,使用ng-click代替element.click():

<card ng-repeat="card in cards" ng-click="test_click('b')"
  ng-style="{left: card.x, top: card.y, 'background-color': card.color}" >

Fiddle

小提琴

When we use any of the pre-built Angular directives -- e.g., ngStyle, ngRepeat, ngClass, ngSwitch, ngShow -- and tie them to models, Angular does the watch()ing for us.

当我们使用任何预先构建的角度指示——例如ngStyle、ngRepeat、ngClass、ngSwitch、ngShow——并将它们与模型绑定时,角度为我们做手表()。

(I don't understand why it only works if I include jQuery. I don't see any jQuery-specific methods being called.)

(我不明白为什么只有包含jQuery才能起作用。我没有看到调用任何特定于jquery的方法。

Update: I figured out how to make it work without jQuery -- add 'px' to the ng-style:

更新:我知道了如何让它在没有jQuery的情况下运行——在ng样式中添加“px”:

<card ng-repeat="card in cards" ng-click="test_click('b')
  ng-style="{left: card.x + 'px', top: card.y + 'px', 'background-color': card.color}" ">

Updated fiddle.

更新的小提琴。

I guess jQuery is more forgiving somehow if we leave off the 'px'.

我猜如果我们去掉“px”,jQuery会更宽容。

To the second fiddle, I also added a "move card #1 down 200px" ng-click/hyperlink, to prove that changing the model results in Angular automatically updating the view for us.

其次,我还添加了“移动卡#1向下200px”的ng-click/hyperlink,以证明更改模型会自动地为我们更新视图。

#2


0  

Ahhhhh, I had the correct approach, the watchers had broken though. Clearly I don't fully understand the semantics of $watch, as I am not totally understanding the solution. I only realised it by printing out the scope and detecting the right variables were present in the isolated scope case.

啊啊啊啊,我找到了正确的方法,但看守者已经崩溃了。显然,我没有完全理解$watch的语义,因为我没有完全理解这个解决方案。我只是通过打印范围和检测在隔离范围情况下存在的正确变量来实现它。

anyway, the solution: I changed the $watch calls to:-

不管怎样,解决方案是:我把$watch的电话改成:-

scope.$watch("x", function (x) {
    element.css('left', scope.x + 'px');
});

and this tracked changes to the bound variables

它跟踪了绑定变量的变化