Angular指令使用click事件注入DOM元素

时间:2016-02-25 20:02:48

标签: angularjs directive insertafter

内容已编辑

目标是创建一个可以附加到文本框的指令,当文本框具有焦点时,文本框后面会出现一个图像/按钮,图像/按钮单击事件将触发指令中包含的函数。目标是使该功能在指令中完全自包含,因此可以在许多页面或应用程序中轻松部署。

图像/按钮出现在文本框之后没有问题,但按钮的单击事件不会触发该功能。我用示例代码创建了一个plunkr

在插件中,第15行定义了一个名为' search,'除了发出警报外什么都没做。当文本框具有焦点时,按钮按预期显示,第34行成功调用搜索功能,这意味着该功能本身正在工作。但是,按钮的点击事件不会触发搜索功能。

原帖

我试图在我们的应用程序中重新创建一些当前使用jQuery完成的功能。该功能涉及将伪类附加到文本框,然后由jQuery拾取,并在文本框之后立即将放大镜的图像注入DOM。单击图像会弹出一个对话框。

到目前为止,我所完成的是一个简单的html页面,一个简单的控制器和一个简单的指令。当文本框具有焦点时,图像将按预期显示。但是,ng-click指令不会触发。

这里是html:         

            <input 
                id="txtAlias" 
                type="text" 
                ng-model="pc.results"
                user-search  />

</div>

这是控制器:

angular
   .module('app')
   .controller('PeopleController', PeopleController);

PeopleController.$inject = ['$http'];

function PeopleController() {

   var pc = this;

   pc.results = '';

   pc.search = function () {
       alert('test');
   };
}

这是指令:

angular
    .module('app')
    .directive('userSearch', userSearch);

function userSearch($compile) {

return {
    restrict: 'EAC',
    require: 'ngModel',
    //transclude: true,
    scope: {
        //search : function(callerid){
        //    alert(callerid);
        //}
    },
    template: "The user's alias is: <b><span ng-bind='pc.results'></span>.",
    //controller: UserSearchController,
    link: function (scope, element, attrs) {
        element.bind('focus', function () {

            //alert(attrs.id + ' || ' + attrs.userSearch);

            var nextElement = element.parent().find('.openuserdialog').length;

            if (nextElement == 0) {
                var magnifyingglass = $compile('<img src="' + homePath + 'Images/zoomHS.png" ' +
                                        'alt="User Search" ' +
                                        'ng-click="pc.search("' + attrs.id + '")" ' +
                                        'class="openuserdialog">')(scope);

                element.after(magnifyingglass);
            }

        });
    }

};

};

目前,我很乐意通过在控制器中点击pc.search或在隔离范围内搜索来获取警报。到目前为止,两者都没有奏效。我确定它缺少一些简单的东西,但我无法弄清楚是什么。

解决方案

感谢Google论坛上的用户向我展示了指令的控制器属性。这个版本现在完美无缺:

angular
.module('app')
.directive('userSearch', userSearch);

function userSearch($compile){

return {
    controller: function ()
        {
            this.search = function () {
                alert('Test');
            };
        },

    link: function (scope, element, attrs) {

        element.bind('focus', function () {

            var nextElement = element.parent().find('.openuserdialog').length;

            if (nextElement === 0) {

                var btn = '<img src="' + homePath + 'Images/zoomHS.png" ' +
                            'ng-click="userSearch.search()" ' +
                            'class="openuserdialog" />';

                element.after($compile(btn)(scope));

            }

        });
    },
    controllerAs: 'userSearch'

};

};

2 个答案:

答案 0 :(得分:0)

您在指令中使用隔离范围,这意味着它无权访问其父范围。因此,在这种情况下,您需要将方法引用显式传递给指令。在隔离的指令范围内通过新变量传递对指令范围的方法引用。

<强>标记

<input id="txtAlias" 
   type="text" ng-model="pc.results" 
   user-search search="search(id)" />

scope: {
   search: '&'
}

由于您无权访问父作用域,因此您不能像使用pc.那样使用控制器别名。只需使用以下没有别名。因此,指令将直接绑定指令范围内的那些变量。

template: "The user's alias is: <b><span ng-bind='results'></span>.",

同时将编译模板更改为

if (nextElement == 0) {
    var magnifyingglass = $compile('<img src="' + homePath + 'Images/zoomHS.png" ' +
      'alt="User Search" ' +
      'ng-click="search({id: ' + attrs.id + '})' +
      'class="openuserdialog">')(scope);
    element.after(magnifyingglass);
 }

相反,我希望将编译的模板仅作为指令函数template的一部分。我将根据ng-if="expression"指令显示和隐藏它。

Relative answer

答案 1 :(得分:0)

而不是尝试注入DOM,然后尝试连接到刚注入的那个东西,而不是在指令中包含输入和搜索按钮/图标。您可以使用隔离范围和双向绑定来连接输入和按钮:

HTML:

  <body ng-controller="MainCtrl">
    <p>Hello {{name}}!</p>
    <search-box data="name" search-function="search"></search-box>
  </body>

这是一个控制器和一个证明这一点的指令。请注意隔离范围中的“=”,在模板中使用该指令时,创建与相应属性的双向绑定。

app.controller('MainCtrl', function($scope) {
  $scope.name = 'World';
  $scope.search= function() { alert('search clicked'); }
});

app.directive('searchBox', function() {
  return {
    restrict: 'E',
    scope: {
      searchFunction: '=',
      data: '=',
    },
    template: '<input ng-model="data" /><button ng-click="searchFunction()">Search</button>'
  }
})

您应该可以使用button或其他任何您想要的内容轻松替换img元素。

这是一个带有alert()的插件,在指令的文本框中输入会影响控制器范围的相应属性: http://plnkr.co/edit/0lj4AmjOgwNZ2DJMSHDj