Content edited
The goal is to create a directive that can be attached to a textbox that, when the textbox has focus, an image/button will appear after the textbox and the image/button click event will fire a function contained within the directive. The goal is for this functionality to be entirely self-contained in the directive so it can be easily deployed in many pages or apps.
The image/button appears after the textbox with no problem but the click event of the button does not fire the function. I have created a plunkr with the example code.
In the plunk, line 15 defines a function called 'search,' which does nothing more than fire an alert. When the textbox has focus, the button appears as expected and line 34 calls the search function successfully, which means the function itself is working. However, the button's click event doesn't fire the search function.
Original post
I'm trying to recreate some functionality in our apps that is currently being accomplished with jQuery. The functionality involves attaching a pseudo-class to a textbox which is then picked up by jQuery and an image of a magnifying glass is injected into the DOM immediately after the textbox. Clicking on the image causes a dialog box to pop open.
What I've accomplished so far is a simple html page, a simple controller, and a simple directive. When the textbox has focus, the image appears as expected. However, the ng-click directive does not fire.
Here's the html:
<input
id="txtAlias"
type="text"
ng-model="pc.results"
user-search />
</div>
Here is the controller:
angular
.module('app')
.controller('PeopleController', PeopleController);
PeopleController.$inject = ['$http'];
function PeopleController() {
var pc = this;
pc.results = '';
pc.search = function () {
alert('test');
};
}
And this is the directive:
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);
}
});
}
};
};
For the time being, I'd be happy to get an alert to fire by either hitting pc.search in the controller or by search in the isolated scope. So far, neither has worked. I'm sure it's something simple that's missing but I can't figure out what.
Solution
Thanks to a user over at the Google forum for showing me the controllerAs property for directives. This version now works perfectly:
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'
};
};
Rather than trying to inject into the DOM, and then trying to hook up to that thing you just injected, wrap both the input and the search button/icon in a directive. You can use an isolated scope and two-way binding to hook up both the input and the button:
HTML:
Here's both a controller and a directive that demonstrate this. Note the "=" in the isolated scope, creating a two-way binding to the corresponding attributes when the directive is used in a template.
You should be able to easily replace the
button
element with animg
or whatever else your heart desires.Here's a plunk with an alert() for the search box, and where typing in the text box in the directive affects the corresponding property of the controller scope: http://plnkr.co/edit/0lj4AmjOgwNZ2DJMSHDj