从jQuery插件访问AngularJS元素

时间:2015-01-08 07:43:19

标签: javascript jquery angularjs

我对AngularJS很新,所以我试着理解它。 因此,当你阅读最初的问题时,请不要开枪。

我正在使用AngularJS开发应用程序。 HTML看起来像这样:

<div id="OfficeUI" ng-controller="Office as Office">

    <div class="absolute">
        <div class="container application-icons icon">
            <img id="{{icon.Id}}" ng-repeat-start="icon in Office.Icons" ng-repeat-end ng-src="{{icon.Icon}}" alt="{{icon.Alt}}" />
        </div>
    </div>

</div>

我的应用程序的控制器看起来像:

var OfficeUI = angular.module('Office');

// Defines the Office controller for the application.
OfficeUI.controller('Office', ['$http', function($http) {
    // Defines required variables.
    var application = this;

    // Get the Json file 'application.json' that defines the application data.
    $http.get('/OfficeUI.Beta/Resources/JSon/application.json')
        .success(function(data) {
            application.Title = data.Title;
            application.Icons = data.Icons;
        })
        .error(function(data) {
            console.error('An error occured while loading the \'application.json\' file.');
        });
}]);

正如您在HTML中看到的那样,我根据特定JSon文件中的数据绑定图像元素。

现在,我希望用户可以将事件添加到给定元素(在本例中为图像)。 因此,我开发了一个看起来像这样的jQuery插件:

(function ( $ ) {
    $.fn.OfficeUI = function(options) {

        var settings = $.extend({
        }, $.fn.OfficeUI.Defaults, options);

        return this;
    }

    $.fn.OfficeUI.Defaults = { };

    $.fn.OfficeUI.bind = function(elementSelector, bound, action) {
        $(elementSelector).on(bound, function() { action(); });

        return this;
    };
}(jQuery));

这个插件允许我调用添加事件如下:

$(this).OfficeUI.bind("icoApplication", "click", function() {
    console.log('The following element is bound.');
});

但是,函数的第一个参数使用选择器来查找要将事件附加到的元素。但是在AngularJS中,由于尚未创建元素,因此无法正常工作。

有任何想法如何解决此问题的人? 我确实希望为用户提供一种干净,简约的方式将事件绑定到应用程序,而无需修改现有的控制器,指令,过滤器......

提前致谢。

3 个答案:

答案 0 :(得分:0)

我不确定我是否理解你的问题是正确的。为什么不在图像上使用ng-click?

<div id="OfficeUI" ng-controller="Office as Office">

<div class="absolute">
    <div class="container application-icons icon">
        <img ng-click="myFunction() id="{{icon.Id}}" ng-repeat-start="icon in Office.Icons" ng-repeat-end ng-src="{{icon.Icon}}" alt="{{icon.Alt}}" />
    </div>
</div>

在你写的控制器中:

// Defines the Office controller for the application.
OfficeUI.controller('Office', ['$scope','$http', function($scope, $http) {
    // Get the Json file 'application.json' that defines the application data.
    $http.get('/OfficeUI.Beta/Resources/JSon/application.json')
        .success(function(data) {
            $scope.Title = data.Title;
            $scope.Icons = data.Icons;
        })
        .error(function(data) {
            console.error('An error occured while loading the \'application.json\' file.');
        });

    $scope.myFunction = function () {
        console.log('The following element is bound.');
    }
}]);

然后将视图绑定到控制器:

<div id="OfficeUI" ng-controller="Office">

<div class="absolute">
    <div class="container application-icons icon">
        <img id="{{icon.Id}}" ng-repeat-start="icon in Icons" ng-repeat-end ng-src="{{icon.Icon}}" alt="{{icon.Alt}}" />
    </div>
</div>

答案 1 :(得分:0)

使用angular directives的正确方法是查看此SO question

this example

示例

App.directive('directiveName', function() {
    return {
        restrict: 'A',
        link: function(scope, element, attrs) {
            $(element).'pluginActivationFunction'(scope.$eval(attrs.directiveName));
        }
    };
}); 

答案 2 :(得分:0)

经过几个小时的搜索,我找到了一个我非常满意的解决方案。

所以,让我们总结一下我现在拥有的东西:

我确实有用于呈现网站的JSon文件,如下所示:

{
  "Title": "Inbox - user@github.com - Outlook",
  "Icons": [
    {
      "Id": "icoApplication",
      "Icon": "Resources/Images/Application/Application.png",
      "Alt": "Outlook"
    },
    {
      "Id": "icoSendReceive",
      "Icon": "Resources/Images/Application/Send-Receive.png",
      "Alt": "Send / Receive"
    },
    {
      "Id": "icoUndo",
      "Icon": "Resources/Images/Application/Undo.png",
      "Alt": "Undo"
    }
  ]
}

然后,我确实使用了使用AngularJS的HTML:

<div class="absolute">
    <div class="container application-icons icon">
        <img id="{{icon.Id}}" ng-repeat-start="icon in Office.Icons" ng-repeat-end ng-src="{{icon.Icon}}" alt="{{icon.Alt}}" />
    </div>
</div>

现在,我确实有客户可以使用这个AngularJS应用程序。我想让用户能够在任何img元素上附加任何事件(点击,滚动,鼠标中心......)。

客户可以在JSon文件中添加元素,但我想避免我的客户需要修改AngularJS模板以附加事件,因为这意味着客户需要在模板中编写条件和其他内容。我会坚持用简单的jQuery / JavaScript来附加事件。

所以,我所做的是创建了一个自定义的AngularJS指令,允许我附加事件。该指令如下所示:

OfficeUI.directive('ngcDynamicEventHandling', function() {
    return {
        restrict: 'A',
        replace: 'true', 
        link: function(scope, element, attributes) {
            var parameter = scope.$eval(attributes['ngcDynamicEventHandling']); // Get the     parameters passed to this directive.

            // Check if an event is attached to this object.
            var registeredEvent = $(this).OfficeUI.searchEvent(parameter);

            // An attached event has been found, so let's register it.
            if (registeredEvent != null) {
                element.on(registeredEvent.handler, function() { 
                    registeredEvent.action();
                });
            }
        }
    };
});

上面的指令接受我在此指令中检索的参数。然后,我确实调用了一个jQuery插件来附加我的事件。

添加指令时的HTML确实如下所示:

<div class="absolute">
    <div class="container application-icons icon">
        <img ngc-dynamic-event-handling="icon.Id" id="{{icon.Id}}" ng-repeat-start="icon in Office.Icons" ng-repeat-end ng-src="{{icon.Icon}}" alt="{{icon.Alt}}" />
    </div>
</div>

现在,让我们转到我的jQuery插件,它允许我注册事件。

(function ( $ ) {
    $.fn.OfficeUI = function(options) {

        var settings = $.extend({
        }, $.fn.OfficeUI.Defaults, options);

        return this;
    }

    $.fn.OfficeUI.Defaults = { };

    var eventCollection = []; // Defines a private collection of registered events.

    $.fn.OfficeUI.bind = function(element, handler, action) {
        eventCollection.push({
            element: element,
            handler: handler,
            action: action
        });
    };

    $.fn.OfficeUI.searchEvent = function(element) {
        var foundElement = $.grep(eventCollection, function(item) {
            return item.element == '#' + element
        });

        if (foundElement.length != 0) {        
            return foundElement[0];
        } 

        return null;
    };
}(jQuery));

因此,第一个重要的函数是bind函数。 可以调用此函数,如:

$(this).OfficeUI.bind("#icoApplication", "click", function() {
    console.log('This method is executed when you click on the application icon.');
});

通过调用上面的函数,我将一个具有某些属性的对象添加到数组中。

$.fn.OfficeUI.bind = function(element, handler, action) {
    eventCollection.push({
        element: element,
        handler: handler,
        action: action
    });
};

现在,让我们再次检查我们的指令:

var parameter = scope.$eval(attributes['ngcDynamicEventHandling']); // Get the parameters passed to this directive.

// Check if an event is attached to this object.
var registeredEvent = $(this).OfficeUI.searchEvent(parameter);

// An attached event has been found, so let's register it.
if (registeredEvent != null) {
    element.on(registeredEvent.handler, function() { 
        registeredEvent.action();
    });
}

我在这里做的是执行我的插件的函数searchEvent,它将检查我是否已将事件注册到放置该指令的元素。

如果是这种情况,该事件将被注册到元素。

所以,这是一个相当长的帖子,但我希望我已经做了一些清楚的事情。 现在,我确实能够将事件附加到AngularJS呈现的HTML,我不需要修改AngularJS模板。更重要的是,我可以附加各种元素,不仅是点击或其他东西。

这为最终用户提供了极大的灵活性。

如果有人对此有任何想法,请不要犹豫回复。