0

内容已编辑

目标是创建一个可以附加到文本框的指令,当文本框获得焦点时,文本框之后将出现一个图像/按钮,并且图像/按钮单击事件将触发包含在指令中的函数。目标是让这个功能在指令中完全独立,以便可以轻松地部署在许多页面或应用程序中。

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

在 plunk 中,第 15 行定义了一个名为“搜索”的函数,它只不过是触发警报。当文本框获得焦点时,按钮按预期显示,第 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 论坛上的一位用户向我展示了用于指令的 controllerAs 属性。这个版本现在可以完美运行:

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'

};

};
4

2 回答 2

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"指令显示和隐藏它。

相对答案

于 2016-02-25T20:05:25.363 回答
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() 的 plunk,在指令中的文本框中键入会影响控制器范围的相应属性:http: //plnkr.co/edit/0lj4AmjOgwNZ2DJMSHDj

于 2016-02-26T21:37:43.627 回答