Refer to this code:
http://plnkr.co/edit/4QpPZZib6qGjhx85Do0M
Here's how to replicate the error:
1. Run the plnkr
2. then click on any of the buttons "200", "300" etc. You will notice that the model updates just fine. No issue so far
3. Now paste something in the input box. The paste should work just fine.
4. Now try clicking on any of the buttons.
ERROR:
You will notice that the values in the input box does not updates to model value.
From what I can understand the issue is with my $render function.. however I can't seem to find a fix for it.
scope.handlePaste = function(e) {
var pastedText = e.clipboardData.getData('text/plain');
ngModelController.$setViewValue(pastedText);
ngModelController.$render = function() {
element.html($sce.getTrustedHtml(ngModelController.$viewValue));
};
return false; //prevent the default handler from running
};
}
You're using ngSanitize but you forgot to include it in the plunker. (lib + injection in app and $sce in directive).
Then element is an angular element and doesn't have an html() function.
You can get the raw html element with element[0] which has a property value.
http://plnkr.co/edit/HSOnscaprbyvUwjr0P2l?p=preview
Related
I am working on a problem wherein I am required to pick-up keydown events (specifically ctrl+p and then point to a print function which already exists) on a certain custom directive and under certain conditions (a certain tab should be selected). My current approach is to bind the keydown event on the document itself, broadcast it and then listen to it in the required custom directive. Following is the code I have placed in the app.run.. block -
angular.element($document).on('keydown', function(evt) {
if(evt.ctrlKey && evt.key==='p'){
$rootScope.$broadcast('printOnKeyPress');
}
});
This part is working as expected, the problem arises when I try to handle it in the required controller of the custom directive as follows:
$scope.$on('printOnKeyPress', function() {
//point to existing print function
}
This is where the problem arises. It goes into the print function but still the output is incorrect. I am missing something and I can't figure out what.
Also, this is not a good approach but I have searched and am unable to find a possible solution to just bind the keydown event on that custom directive itself (the component only appears if a document is selected).
(ng-keydown won't also work here)
Any help is appreciated!
You could put it in the directive and use the scope destroy event to remove the listener.
Within directive link function:
function keyHandler(evt) {
if (evt.ctrlKey && evt.key === 'p') {
// do your print
}
}
angular.element($document).on('keydown', keyHandler);
scope.$on('$destroy', function() {
angular.element($document).off('keydown', keyHandler);
});
I have a div populated dynamically with input elements and setting the focus on the first input field. The focus works on Chrome but not on IE. Here is the plnkr http://plnkr.co/edit/b6urKKilDVRwuqVQfbWt
The focus is in fact done inside a timeout function but still the focus does not seem to do anything on the input field. I am using an angular directive to create my form elements.
directive('ngppParameters', ["$compile","$timeout",function($compile,$timeout) {
return {
restrict: 'E',
link:function($scope,$element,$attrs)
{
$scope.$watch("tree.length", function (value) {
if(value.length===0)
return;
$timeout(function() {
var fields = $("ngpp-parameters input").filter(":visible:first");
console.log("Setting the focus");
if(fields.length>0)
{
console.log("Setting focus");
fields[0].focus();
}
},10);
});
}
};
Update:
This is the directive.
Finally found the issue, IE is treating the disabled parent and not letting the focus to be set on the children.
I have removed the disabled="disabled" attr from the directive pp-field and it works as expected. All other browsers except IE are not considering the parents disabled state.
Make sure you use ng-disabled="" instead of disabled attribute to make browsers to ignore it and behave as expected.
fields[0] isn't what you think it is (i've been caught by this same mistake before).
You want fields.eq(0)
https://api.jquery.com/eq/
You might also be able to just called fields.focus(). If there's only one in there that should work.
Requirement
I want a textarea that expands or contracts vertically as the user types, alla Facebook comment box.
When the textarea loses focus it contracts to one line (with ellipsis if content overflows) and re-expands to the size of the entered text upon re-focus (this functionality not found on Facebook)
Note: Clicking on the textarea should preserve caret position exactly where user clicked, which precludes any dynamic swapping of div for textarea as the control receives focus
Attempted Solution
I'm already well into an AngularJS implementation, so...
Use Monospaced's Angular Elastic plugin. Nice.
Two attempts...
Attempt A: <textarea ng-focus="isFocussed=true" ng-blur="isFocussed=false" ng-class="'msd-elastic': isFocussed"></textarea> Fails because ng-class triggers no re-$compile of the element after adding the class, so Angular Elastic is never invoked
Attempt B: create a custom directive that does the needed re-$compile upon class add. I used this solution by hassassin. Fails with the following problems
Attempt B problems
Here's a JSFiddle of Attempt B Note that Angular v1.2.15 is used
I. Disappearing text
go to the fiddle
type into one textarea
blur focus on that textarea (eg click in the other textarea)
focus back on the text-containing textarea
result: text disappears! (not expected or desired)
II. Increasingly excessive looping and eventual browser meltdown
click into one textarea
click into the other one
repeat the above for as long as you can until the browser stops responding and you get CPU 100% or unresponsive script warnings.
you'll notice that it starts out OK, but gets worse the more you click
I confirmed this using: XP/Firefox v27, XP/Chrome v33, Win7/Chrome v33
My investigations so far
It seems that traverseScopesLoop in AngularJS starting at line 12012 of v1.2.15, gets out of control, looping hundreds of times. I put a console.log just under the do { // "traverse the scopes" loop line and clocked thousands of loops just clicking.
Curiously, I don't get the same problems in Angular v1.0.4. See this JSFiddle which is identical, except for Angular version
I logged this as an AngularJS bug and it was closed immediately, because I'd not shown it to be a bug in Angular per se.
Questions
Is there another way to solve this to avoid the pattern in Attempt B?
Is there a better way to implement Attempt B? There's no activity on that stackoverflow issue after hassassin offered the solution I used
Are the problems with Attempt B in my code, angular-elastic, hassassin's code, or my implementation of it all? Appreciate tips on how to debug so I can "fish for myself" in future. I've been using Chrome debug and Batarang for a half day already without much success.
Does it seem sensible to make a feature request to the AngularJS team for the pattern in Attempt A? Since you can add directives by class in Angular, and ngClass can add classes dynamically, it seems only natural to solve the problem this way.
You are severely overthinking this, and I can't think of any reason you would ever need to dynamically add / remove a directive, you could just as easily, inside the directive, check if it should do anything. All you need to do is
Use the elastic plugin you are using
Use your own directive to reset height / add ellipsis when it doesn't have focus.
So something like this will work (not pretty, but just threw it together):
http://jsfiddle.net/ss6Y5/8/
angular.module("App", ['monospaced.elastic']).directive('dynamicClass', function($compile) {
return {
scope: { ngModel: '=' },
require: "?ngModel",
link: function(scope, elt, attrs, ngModel) {
var tmpModel = false;
var origHeight = elt.css('height');
var height = elt.css('height');
var heightChangeIndex = 0;
scope.$watch('ngModel', function() {
if (elt.css('height') > origHeight && !heightChangeIndex) {
heightChangeIndex = scope.ngModel.length;
console.log(heightChangeIndex);
}
else if (elt.css('height') <= origHeight && elt.is(':focus')) {
heightChangeIndex = 0;
}
});
elt.on('blur focus', function() {
var tmp = elt.css('height');
elt.css('height', height);
height = tmp;
});
elt.on('blur', function() {
if (height > origHeight) {
tmpModel = angular.copy(scope.ngModel);
ngModel.$setViewValue(scope.ngModel.substr(0, heightChangeIndex-4) + '...');
ngModel.$render();
}
});
elt.on('focus', function() {
if (tmpModel.length) {
scope.ngModel = tmpModel;
ngModel.$setViewValue(scope.ngModel);
ngModel.$render();
tmpModel = '';
}
});
}
};
})
Based on this question, though I felt this warranted its own question: Google pagedown AngularJS directive
Following the example from this question, it seems to work, however I am running into issues when I try to append a directive to the page.
Here is the code I have in the linking function:
scope.editor_id = null;
if(attrs.id == null) {
scope.editor_id = nextID++;
} else {
scope.editor_id = attrs.id;
}
//append editor HTML
//has to be done here so that it is available to the editor when it is run below
var editor_html = $compile(
'<div id="wmd-button-bar-' + scope.editor_id + '"></div>' +
'<textarea class="wmd-input" id="wmd-input-' + scope.editor_id + '" ng-model="content"></textarea>'
)(scope);
element.find('.wmd-panel').append(editor_html);
var editor = new Markdown.Editor(editor_converter, "-" + scope.editor_id);
editor.run();
However, when I append one of these to the document, I get the following error:
TypeError: Cannot read property 'attachEvent' of null
This error tends to crop up when the wmd-input is not present in the HTML. however, I am adding it with the $compile function, and it works on page load, but not when it is appended. What am I doing wrong here?
UPDATE
I was able to reproduce your problem: http://plnkr.co/edit/R2eDKBreHmYBjPtU0JxD?p=preview
Why typeError: Cannot read property 'attachEvent' of null?
I was wrong with my previous assumption ( the composite linking function do returns the element)
The problem is with the way you use angular.element#find.
angular.element#find only search for child elements not on the whole document.
the DOM element with a .wmd-panel class is not a child of the current element.
This should work fine:
angular.element('.wmd-panel').append(editor_html);
Try doing compile like this:
$compile('template stuff goes here')(scope, function(cloned, scope){
element.append(cloned);
});
You may also have to define your editor inside the callback function because I'm not sure if it's asynchronous or not. You may also want to re-consider having your directive compile and append to itself like this. Why not just add more instances of the entire directive using something like ng-repeat?
Also, if you have multiple instances inside this one directive, you will lose reference to editor. Not sure what's going on outside this code so I can't really tell.
1) I have a store called "Job". Is correct that method "getJobStore" is automatically created.
2) in the following code example. I get this error. "this.getJobStore is not a function". When i go console.info(this) i do not see this function. So what property should be "this" ?
onSubmitBtnClick: function () {
var form = Ext.getCmp('formJobSummary');
var record = form.getRecord();
var values = form.getValues();
this.getJobStore().sync();
},
Make sure that you have set the scope properly for your onSubmitBtnClick listener. My guess is that it is running in the scope of your button, not your controller (that is, you haven't specified scope: this in your listener configuration). If you post the configuration of the controller entirely, we would be able to say for sure.
this should be a controller object which is listening the events of this button (as example).
Is that true for you now?