Trigger ngf-select programmatically - javascript

I have a directive that should open file picker window when a controller variable changes. Here is the snippet of the directive:
angular.module('settingsInternal')
.directive('triggerUpload', function ($timeout) {
return {
restrict: 'A',
link: function (scope, element) {
scope.$watch('mainCtrl.watchedVariable', function (variable) {
if (variable) {
$timeout(function () {
element.triggerHandler('click');
}, 20);
}
});
}
};
});
The problem I'm having is that I cant trigger the ngf-select on the div. It works perfectly fine when manually clicking on the div, and the watch function calls element.triggerHandler('click') properly. I have wasted several hours trying to figure out the reason why this doesn't work, if someone had a similar problem please help me figure out where the problem lies.
P.s. Dont pay attention to variable names, they are for demonstrational purposes.

The problem wasn't in angular's ngf-select but in the input[type=file], which the directive uses. Input[type=file] has to be initialized by user made event, so if you want to open file upload window with a function you have to call that function from a user made event.
I hope this helps someone that has experienced a similar problem.

Related

Class directive doesn't work, but works whenever changed to element directive

I'm encountering a very weird issue where class directives just will not work. So I'm trying to implement the following directive.
appModule.directive('btn', function () {
return {
restrict: 'C',
link: function (scope, element) {
if (element.hasClass('btn-icon') || element.hasClass('btn-float')) {
Waves.attach(element, ['waves-circle']);
}
else if (element.hasClass('btn-light')) {
Waves.attach(element, ['waves-light']);
}
else {
Waves.attach(element);
}
Waves.init();
}
}
});
Then In my HTML I just have a button with the class btn, like so.
<button type="button" class='btn btn-success'>Hello</button>
But for some reason it just won't EVER fire the directive. I've tried debugging using console.log, it's just not entering the directive itself. But when I change restrict: 'C' from C to E, it works fine! (with altered HTML ofcourse.)
Now we do use a small framework on top of angularJS, but haven't found anything weird in there. (I recently joined the team, and the orignal developer of the framework didn't write any documentation and has left the team).
What could possibly be a reason why this directive would not work? I've googled everywhere but I can't find anyone with a similar issue.
So after looking at the code for hours, I finally found what it was. So someone that wrote the official code added in this line of code....
$compileProvider.cssClassDirectivesEnabled(false);
Changed this to true, and it works..

Angular, How to implement the below code on resize as well as on load

angular.module(module.name).directive(current.name, ['$timeout', function (timeout) {
return {
restrict: 'A',
link: function (scope, element, attrs) {
element[0].style.margin = '0.1px';
timeout(function () {
element[0].style.margin = '0px';
}, 3000);
}
}
}]);
The above angular code is something that I wrote so when the browser loads it'll repaint the browser after to show the content on a single page app properly. However I have come to another issue where I need to do this on Resize.
I want to be able to use the same function below and add resize to it.. I'm a bit lost if I can add resize to this or will I need to write a different script.
I'm still coming to grips with angular so I'm looking for an answer that will explain this properly and what would be the best practise for what I want.
Do you want to apply it on any resize of the window or just below particular ratio/size?
If you want on any resize of the window, take a look at this JSFiddle
scope.$watch(scope.getWindowDimensions, function (newValue, oldValue) {...

Angular directive breaks scope?

First off, I'm new to Angular, and realize that I may be missing a core concept...
Consider the jsfiddle: http://jsfiddle.net/D4dFv/
I'd like to be able to click on each link, and see the {{driveState.currentView}} update in the DOM.
Everything works fine until I add in a directive that helps me detect when all images on the page have loaded successfully. With that directive in place, the binding appears to break, and you can no longer click on each link and see driveState.currentView update.
Why is this?
To test this in the jsfiddle, note that the following works fine:
<img width='10' height='10' src='http://www.w3schools.com/images/pulpit.jpg'>
...and this breaks the data binding somehow:
<img imageonload width='10' height='10' src='http://www.w3schools.com/images/pulpit.jpg'>
Thanks in advance.
The reason is that the Directive is defining its own controller. This makes a new instance of the controller class and is somehow messing up the scope.
To fix, take out the controller: 'Ctrl', in the Directive definition.
Here is the new Directive code:
myApp.directive('imageonload', function () {
return {
restrict: 'A',
link: function ($scope, element) {
element.bind('load', function () {
_viewsLoaded++;
if (_viewsLoaded === $scope.appViews.length) {
alert('init layout here');
}
});
}
};
});
And an updated fiddle for you.

set angular-ui-tinymce editor content after navigation

I'm using angular-ui-tinymce (latest version 0.0.4, https://github.com/angular-ui/ui-tinymce/blob/master/src/tinymce.js).
I've encountered a problem I cannot solve.
On the first page load, content is loaded to the editor via ng-model.
Then I navigate to another state and then navigating back to state with the editor.
The value still exists on the scope (I've checked it) but the content doesn't appear in the editor for some reason I cant figure..
This is the the textarea with the directive as attribute:
<textarea rows="10" class="form-control" id="desc" ui-tinymce ng-model="valueFromScope"></textarea>
This changes happened after updating AngularJS from 1.5 to 1.2.1.
I thought it had something to do with ngSanitize but I'm not sure..
btw angular-sanitize and ngSanitize are included in the app.
Any advice?
update
It seems like ngModel.$render is not doing anything.
ngModel.$render = function() {
console.log(ngModel);
tinyInstance = tinymce.get(attrs.id);
if (tinyInstance) {
tinyInstance.setContent(ngModel.$viewValue || '');
updateView();
}
};
Nothing is printed out, not even undefined, this means ngModel.$render doesn't even run.
Any reasons for that?
Update
I don't think model.$render is related, from what I understand $render only executes on a programmatic change like actually editing the text and that works..
I still can't figure it out, sometimes the value is shown and sometimes not.
Problem Solved! - for now..
Thanks to #alonisser I've found a solution.
From what I understand, the problem is occurring because something has changed in the prioritizing of angularjs directives.
read the following:
http://iwang.github.io/html/angular/angularjs/2013/11/04/ngmodel-render-cannot-be-overriden-in-angular-rc3.html
the simple fix is just to add priority definition to the directive
return {
priority: 10,
require: 'ngModel',
Setting the priority doesn't really solve the problem.
The only thing that worked for me was adding the following code before the ngModel.$render = function()
var stopWatch = scope.$watch(attrs.ngModel, function(newValue){
if (!tinyInstance){
tinyInstance = tinymce.get(attrs.id);
}
if (tinyInstance) {
tinyInstance.setContent(newValue);
stopWatch();
}
});

Prevent default anchor behaviour AngularJS

When the user clicks a link, I want to execute some code in a function inside the controller. But I want to prevent that the URL changes.
I tried the following possibilities
Removed the href-attribute. Didn't work, still changes the url to '/'
Tried ng-click='deleteUser(user.id, $event)' and $event.preventDefault() in my deleteUser()-function. Didn't work.
What did work is a hack I've found on GitHub about an unintended reload.
This is how I do it now:
<a ng-click="deleteUser(user.id)" href="javascript:">Delete user</a>
Question
What is the'clean' method to prevent a link from changing the URL?
<a ng-click="deleteUser(user.id)" href="">Delete user</a>
If you look at the source code for the a element directive (which is a part of the Angular core), it states at line 29 - 31:
if (!element.attr(href)) {
event.preventDefault();
}
Which means Angular already is solving the issue of links without a href. The only issue you still have is the css problem. You can still apply the pointer style to anchors that have ng-clicks, e.g.:
a[ng-click] {
/* Styles for anchors without href but WITH ng-click */
cursor: pointer;
}
So, you could even make your site more accessible by marking real links with a subtle, different styling then links that perform functions.
Happy coding!
The real problem is in the a directive
That's right, every <a></a> element is actually an AngularJS directive.
It seems to fix some issues with IE if you look the comments in the code.
But everything for me is working great when I just removed the directive from the AngularJS core code.
I was having the same problem as you did and tried all of the other solutions. The difference is that I had the problem only in IE.
If you don't want to play with building the AngularJS script from source, just search for htmlAnchorDirective in the angular.js file and remove/comment it out.
I believe there is a bigger problem here which should be addressed in the AngularJS core, but I haven't found it yet.
UPDATE: This solution is most probably outdated now! You should try using the latest AngularJS version.
What exactly didn't work when you removed the href attribute?
That's exactly what you should do. See this fiddle for an example:
http://jsfiddle.net/terebentina/SXcQN/
As #Justus pointed out, if the source code is like:
if (!element.attr(href)) {
event.preventDefault();
}
Making element.attr(href) as null string '' should get you inside the if condition, as !'' evaluates to true. That is the solution by #umur
I have always been doing deleteUser($event,user.id) and it seemed to work. A possible problem would be the ordering of the variables to your click handler. The first argument should probably be the $event object.
I use my custom directive to accomplish this. Its mechanism is to operate ng-click directive itself.
angular.module('delete', [])
.directive('buttonDelete', ['$parse', function ($parse) {
var confirmFunc = function (scope, element, attr, event, ngClick) {
if (! confirm("Are you sure?")) {
event.preventDefault();
}
else {
// Copy from ngEventDirectives initialization.
var fn = $parse(ngClick);
scope.$apply(function() {
fn(scope, {$event:event});
});
}
};
return {
restrict: 'C',
compile: function (element, attr) {
var ngClick = attr.ngClick;
attr.ngClick = '';
return {
pre: function (scope, element, attr) {
element.click(function (e) {
confirmFunc(scope, element, attr, e, ngClick);
});
}
};
}
};
}]);
This is admittedly a hack, but I did:
<span class="link" ng-click="deleteUser(user.id)">Delete user</span>
and in my css had
span.link {
/* style like a link */
}
The following worked great for me:
<a ng-href="javascript: return false;" ng-click="alertSearchCtrl.deleteAlert()">Remove</a>

Categories