i tried to include http://krescruz.github.io/angular-materialize/#select and i got error in console (you can see in image). Is there any solution for this issue, here is the directive which is in angular-materialize.js
angular.module("ui.materialize.material_select", [])
.directive("materialSelect", ["$compile", "$timeout", function ($compile, $timeout) {
return {
link: function (scope, element, attrs) {
if (element.is("select")) {
$compile(element.contents())(scope);
function initSelect() {
element.siblings(".caret").remove();
element.material_select();
}
$timeout(initSelect);
if (attrs.ngModel) {
scope.$watch(attrs.ngModel, initSelect);
}
if ("watch" in attrs) {
scope.$watch(function () {
return element[0].innerHTML;
}, function (oldVal, newVal) {
if (oldVal !== newVal) {
$timeout(initSelect);
}
});
}
}
}
};
}]);
This error means that you are trying to use jQuery methods without loading jQuery. Angular comes with lightweight jQuery-like implementation (angular.element) with limited set of methods. Those methods don't include is and trigger (and many others).
So the solution is simple: if you use jQuery methods - load jQuery before Angular.
Related
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"});
});
}
}
}]);
I'm trying to apply a CSS style in an element within a certain route. For this I have created a directive where I add the class when $state.include includes the location, but since the path keeps changing it needs to watch for changes in the $state, but it is not working. Here is my code:
angular
.module('pharm')
.directive('flApplyStyle',['$stateParams','$state',applyStyle]);
function applyStyle($stateParams,$state) {
return {
link: function(scope, element, attributes){
console.log($state.current);
scope.$watch($stateParams, function (newValue, oldValue) {
if ($state.includes("app.calc.edit")) {
element.addClass('BackgroundEdit');
}else{
element.addClass('none');
}
});
}
}
};
This should probably work. Tap into the $stateChangeStart event and then check for changes to $state. If that event doesn't work, try $stateChangeSuccess.
angular
.module('pharm')
.directive('flApplyStyle', ['$rootScope','$state', applyStyle]);
function applyStyle($rootScope, $state) {
return {
link: function(scope, element, attributes){
$rootScope.$on('$stateChangeStart', function () {
if ($state.includes("app.calc.edit")) {
element.addClass('BackgroundEdit');
} else {
element.addClass('none');
}
});
}
}
}
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/
So here is what my issue is:
i have a directive:
autocompleteDirective.$inject = ['$timeout'];
function autocompleteDirective($timeout) {
return {
restrict: 'E',
scope: {
searchParam: '=ngModel',
suggestions: '=data',
onType: '=onType',
onSelect: '=onSelect',
autocompleteRequired: '='
},
controller: autocompleteController,
link: autocompleteLink,
templateUrl:'modules/components/autocomplete/templates/autocomplete.html'
};
}
my Link function looks like this:
function autocompleteLink(scope, element, attrs) {
$timeout(function() {
scope.initLock = false;
scope.$apply();
}, 250);
.... some other code
}
and my controller (not really relevant) :
autocompleteController.$inject = ['$scope'];
function autocompleteController($scope) {
//scope code
}
in my link function, I have a function that is (at the moment) using setTimeout:
if (attrs.clickActivation) {
element[0].onclick = function() {
if (!scope.searchParam) {
setTimeout(function() {
scope.completing = true;
scope.$apply();
}, 200);
}
};
}
I would like to unit test this certain block of code, but my unit tests fails:
elem.triggerHandler('click');
expect(scope.completing).to.equal(true);
even though, in the coverage report, i can see that the logic does successfully execute when the triggerHandler is clicked.
what i believe the culprit is the timeout.
digging around SO and other websites, i found using $timeout works best due to its exposure to "flush()" method.
my question is, how do I "inject" $timeout to the link function?
the previous examples i have see like injecting $timeout directly to directive, and then nesting the link function() inside the directive declaration:
function directive($timeout){
return {
link: function(scope, attrs) {
$timeout(blah!) //timeout is useable here...
}
}
The above doesn't work for me since i am not creating the function inside the directive function...so based on the model i am using, how can i use $timeout in a link?
Just changed to Angular 1.2.0-rc.3 (from 1.2.0-rc.2) and directive for inline Editor doesn't work anymore.
Works fine in normal mode but not inline.
Does anyone knows how to fix this?
Thanks.
app.directive('uiCkeditor', [function() {
return {
require: '?ngModel',
link: function(scope, element, attrs, ngModel) {
if (!ngModel)
return;
ngModel.$render = function(value) {
ck.setData(ngModel.$viewValue);
}
// var ck = CKEDITOR.replace(element[0]);
var ck = CKEDITOR.inline(element[0])
ck.on('pasteState', function() {
ngModel.$setViewValue(ck.getData());
scope.$apply();
});
}
}
}])
I used ng-bind-html to render what is in the model and I created the directive ck-inline to add the inline feature and bind the model to the changes that happen in the inline editor. This directive requires a ng-bind-html to work and you also need to have ngSanitize added to your module. Add directive ck-inline to your element and it should work fine.
I would recommend you to use a different directive for the regular editor since it has a different behavior and can work well enough with just the ng-model directive.
I also use $timeout because I noticed that if I don't the text is rendered and then ckeditor somehow deletes all the values which messes up the model (this does not happen with the non-inline option). Here is the code.
yourModule.directive('ckInline', ['$sce', '$timeout', function($sce, $timeout){
return{
require : '?ngBindHtml',
scope:{value:"=ngBindHtml"},
link : function(scope, elm, attr, ngBindHtml)
{
$timeout(function()
{
var ck_inline;
elm.attr("contenteditable", "true");
CKEDITOR.disableAutoInline = true;
ck_inline = CKEDITOR.inline(elm[0]);
if (!attr.ngBindHtml)
return;
ck_inline.on('instanceReady', function()
{
ck_inline.setData(elm.html());
});
function updateHtml()
{
scope.$apply(function()
{
scope.value = $sce.trustAsHtml(ck_inline.getData());
});
}
ck_inline.on('blur', updateHtml);
ck_inline.on('dataReady', updateHtml);
});
}
};
}]);