Angular Js - emit from $rootScope within directive - angularjs

I am trying to open dialogs, which have their own Controllers, opening them through events.
My problem now is, that I am always getting
Cannot read property $emit of undefined`, because for some reason
my $rootScope is undefined.
How can I inject the $rootScope properly?
I am using Angular 1.6.7.
.directive("opendialog", [function($rootScope) {
return {
link: function(scope, element, attributes) {
element.bind("click", function(event) {
var dialogId = $(element).attr("id");
$rootScope.$emit(dialogId, {
command: "open"
});
});
}
}
}]);

Try this
.directive("opendialog", ["$rootScope", function ($rootScope) {
return {
link: function (scope, element, attributes) {
element.bind("click", function (event) {
var dialogId = $(element).attr("id");
$rootScope.$emit(dialogId, {command: "open"});
});
}
}
}]);

Related

Angularjs directive set scope var in directive and access in controller

Hi I am working on angularjs. I am facing an issue in directive.
I have set the scope.user.name="amin shah" on link/click event
and want to access this in controller how is this possible?
var dataSourceDirective = angular.module('mydirective', []);
dataSourceDirective.directive('dir', function () {
return {
restrict: 'C',
scope: true,
link: function ($scope, element, attrs) {
element.bind('click', function () {
$scope.user.name ="amin shah";
$scope.$apply();
$('.sourceType_panel').hide();
$('#sourceType_1_panel').show();
});
}
}
});
controller code
$scope.demo = function () {
console.log($scope.user);`
},
You need to create Isolated scope in your directive.
The given controller should be parent of this directive.
var dataSourceDirective = angular.module('mydirective', []);
dataSourceDirective.directive('dir', function () {
return {
restrict: 'C',
scope: {user:"=user"},
link: function ($scope, element, attrs) {
element.bind('click', function () {
$scope.user.name ="amin shah";
});
}
}
});
In html :
<div ng-copntroller='yourCtrl'>
<dir user="user"></dir>
</div>
In Controller you should initialize the user.
OR
you use $broadcast & $emit if the parent is controller.
Withing link function of directive you can use $rootScope.$emit('user_name_update',user);
And in the controller you can listen this event
$scope.$on('user_name_update',function(data){
console.log(user) // its should give your updated `user` object
})
First of all you should correct your link method and I think you shouldn't need child sope at there. So you should delete your scope bind in directive too. You can reach parent scope with link method.
app.directive('dir', function () {
return {
restrict: 'E',
link: function (scope, element, attrs) {
element.bind('click', function () {
scope.user.name ="amin shah";
scope.$apply();
});
}
}
});
and in your controller you can define scope variable like that:
app.controller('MainCtrl', function($scope) {
$scope.user = {
name: ''
}
});
also you should add this directive to HTML :
<dir>Element</dir>
<p>{{user.name}}</p>
here is the working plunkr you should click Element than you can see your name from directive but in parent scope
https://plnkr.co/edit/umTdfukZ22hARoLjxdL3?p=preview

$timeout is not working in my code. Im trying to delay the html elements to display after specific time using this directive

Here is the code I'm using. I'm trying to display the html contents which comes under this tag after 4 seconds
Utils.directive('ieUtilsError', function() {
var directive = {};
directive.link = function(scope, element, attrs) {
element.attr("style","display:none")
function show() {
element.attr("style","display:inline")
}
$timeout(function() {
show();
}, 4000);
}
});
$timeout is a service which should be injected. Change the below line
Utils.directive('ieUtilsError', function() {
//your code
});
to
Utils.directive('ieUtilsError', function($timeout) {
//your code
});
Include the $timeout dependency in your directive, like this:
Utils.directive('ieUtilsError', function($timeout) {
//your code...
});
You didn't inject the $timeout service in your directive, so it's undefined:
Utils.directive('ieUtilsError', function($timeout) {
You also forgot to return the directive from the function:
return directive;
Otherwise, it works fine: http://plnkr.co/edit/z0P6ENRyXvyYjNr7KqzV?p=preview
Note that is couls be reduced to
Utils.directive('ieUtilsError', function($timeout) {
return {
link: function(scope, element, attrs) {
element.attr("style","display:none")
$timeout(function() {
element.attr("style","display:inline");
}, 4000);
}
};
});
You need to inject $timeout into your directive
Utils.directive('ieUtilsError', ['$timeout',ieUtilsError]);
function ieUtilsError($timeout){
return {
$timeout(function() {
element.attr("style","display:inline");
}, 4000);
};
}
You need to inject dependencies to the directive like in other modules:
Utils.directive('ieUtilsError', ['$timeout', function($timeout) {
return = {
link: function($scope, element){
element.attr("style","display:none")
//use $timeout
$timeout(function() {
element.attr("style","display:inline");
}, 4000);
}
};
}]);

Typeerror - Not a function in angular directive

I have defined a custom click directive as below:
(function() {
'use strict';
angular.module('myApp.core')
.directive('customClick', customClick);
customClick.$inject = ['$rootScope'];
function customClick() {
return {
restrict: 'A',
/*scope: {
customClick: '&'
},*/
link: function(scope, element, attrs){
$(element).on('click', function(e) {
scope.$apply(function() {
console.log("Hello..customClick..");
scope.customClick();
});
});
}
};
}
})();
And I get the following error on this;
Error logged by WDPR Angular Error handler service {xx.."stacktrace":"TypeError: a.customClick is not a function","cause":"unknown cause"}(anonymous function)bowerComponents.js:5745
How can I resolve this? If I add scope with '&' I get demanding isolated scope. Hence how to resolve it?
If I remove - scope.customClick();, it does not show anything on second html for custom-click, it has impact on only 1 html, and its controller. I want to use it in multiple controller + html.
customClick is a function on the directive itself. It is not a function on the scope. That's why the error has occurred.
link is used to manipulate dom/add event handlers on elements, which you have rightly done with element.bind('click', function() {
Whenever click occurs, the function binded to click automatically gets invoked. There is no need of watch and the invoking statement.
Your link can just be
link: function(scope, element){
element.bind('click', function() {
console.log("Hello..customClick..");
});
}
As you have used camel case in naming the directive, exercise caution in its usage in template.
You can use it as <p custom-click>hi</p>
I would recommend you to avoid using jQuery in angular apps. Try following
angular.module('newEngagementUI.core')
.directive('customClick', customClick);
customClick.$inject = ['$rootScope'];
function customClick() {
return {
restrict: 'A',
scope: {
customClick: '&'
},
link: function(scope, element, attrs){
element.bind('click', function () {
scope.customClick();
})
}
};
}
In your template:
<div custom-click="clickFunction"></div>
And your template controller should be like:
angular.module('myApp', []).controller(['$scope', function ($scope) {
$scope.clickFunction = function () {
alert('function passed');
}
}])
Working fiddle here: https://jsfiddle.net/xSaber/sbqavcnb/1/

Can't use a Directive Controller AND Require a Directive Controller (and have them both be available)

So I have a validation directive that should work with ng-form. I need to use their controller but also I need to bind the elements click event to my own controller. If I just use require I can access that form controller, if I just use controller I can access my controller, but if I use both require and controller I only get access to the required controller!
angular.module('app')
.directive('myValidation', function() {
return {
controller: function MyController() {
},
link: function($scope, ele, attr, MyCtrl) {
// All is well
}
};
})
.directive('myValidationTwo', function() {
return {
require: 'form',
controller: function MyController() {
},
link: function($scope, ele, attr, formCtrl) {
// MyCtrl is not available!
// formCtrl is not an array of controllers!
}
};
});
Seems like a major oversight if this isn't possible!
You just need to require it specifically.
angular.module('app')
.directive('myValidation', function() {
return {
controller: function MyController() {
},
link: function($scope, ele, attr, MyCtrl) {
// All is well
}
};
})
.directive('myValidationTwo', function() {
return {
require: ['myValidationTwo', 'form'],
controller: function MyController() {
},
link: function($scope, ele, attr, ctrl) {
var MyCtrl = ctrl[0];
var formCtrl = ctrl[1];
}
};
});

Passing ng-click/ng-submit promise to directive

Basically, I created a directive that passes a promise to the link function from ng-click and and detects when the promise is done so that I can attach a class to it.
Example:
.directive('myDirective', function($parse) {
return {
restrict: 'A',
scope: {
ng-click: '&'
},
link: function(scope) {
var d = $parse(scope.ngClick);
element.on('click', function(event) {
d().then(function() {
element.addClass(attrs.myDirective);
});
});
}
};
});
<element ng-click="promise();" my-directive="class"></element>
//controller function
$scope.promise = function() {
return promise().then(function() {});
}
It is doing what I want except that the controller function is getting called three times. I would really like to just use require: '^ngClick' here but since the ngClick directive does not have any controllers, I can't do that. Can anyone point me in the right direction? Thanks!
Added event.preventDefault() to the event.on('click') function in the link of my directive:
element.on('click', function(event) {
event.preventDefault();
d().then(function() {
element.addClass(attrs.myDirective);
});
});

Resources