Getting event.key as undefined intermittently on "keydown" event, with Chrome browser - javascript

I am using the code below in an angular custom directive code to know the keys pressed. It works fine however event.key starts giving undefined intermittently. If i am clearing the cache and trying it again, it starts working again. What could be the possible issue ?
<input type="text" input-styler="" class="form-control" id="input-phrase" ng-model="home.inputPhrase" autocomplete="off">
angular
.module('myApp')
.directive('inputStyler', inputStyler);
function inputStyler() {
var directive = {
restrict: 'A',
link: link
};
function link(scope, element, attrs){
element.bind("keydown", function (event) {
console.log(event.key);
if((!event.ctrlKey) && (event.key !== " ") && (event.key.length == 1)){
scope.home.inputPhrase += event.key;
}
});
element.on("cut copy paste", function(event){
event.preventDefault();
});
};
return directive;
}

Related

Call scope function inside onkeydown event

I have the following html:
<input type="checkbox" ng-model="user.show_value" ng-blur="update_show_value()">
A value (true / false) is fetched from the database and passed to the ng-model. Depending on it, the checkbox is checked / uncheked. The function inside ng-blur triggers the update in the database and works:
$scope.update_show_value() = function() {
if ($scope.user.show_value != undefined) {
$scope.loading = true;
//IF VALUE IS VALID, CALL THE UPDATEPIN FUNCTIONn
User.updatevalue($scope.user)
//IF SUCCESSFUL, GET VALUE
.success(function(data) {
$scope.loading = false;
$scope.formData = {}; //CLEAR FORM SO THAT USER CAN ENTER NEW DATA
$scope.user.show_value = {type : $scope.user[0].show_value}; //PASS VALUE IN OUR SCOPE
});
}
};
The issue is that I would have to use the checkbox from other devices that don't support the click event. From these devices I should use the equivalent of enter (keycode 13). So I added the onkeydown event to detect when the enter key is being pressed on the checkbox. Using an example from w3schools, I see it works (here is the example http://www.w3schools.com/jsref/tryit.asp?filename=tryjsref_event_key_keycode3)
<input type="checkbox" ng-model="user.show_value" onkeydown="keyCode(event)" ng-blur="update_show_value()">
Now I want to call the update function when the onkeydown event detects that the code 13 was pressed. Something like this:
<script>
function keyCode(event) {
var x = event.keyCode;
if (x == 13) {
alert ("You pressed the Escape key!");
update_show_value();
}
}
</script>
However, calling update_show_value inside the keycode function does not work. Actually, adding update_show_value inside the keycode function causes everything else not to work (ex. the alert)
So for some reason I think that scope functions cannot be called inside javascript functions. If that is true, is there a workaround?
You can get the scope object outside of Angular by using:
angular.element(event.target).scope(); // and then call whatever functions you want to on that scope object
You can define your own directive to handle keydown
angular.directive('myKeydown', [ function () {
return {
link: function(scope, elem, attrs) {
element.bind('keydown', function() {
scope.update_show_value();
});
}
};
}]);
Or just use ng-keydown instead: https://docs.angularjs.org/api/ng/directive/ngKeydown :
$scope.keyCode = function($event) {
. . .
$scope.update_show_value();
};
Remove () from $scope.update_show_value
Try Below Code:
<script>
var app=angular.module("myApp", []);
app.controller("myCtrl", function($scope) {
$scope.update_show_value = function() {
alert(1);
};
});
</script>

scope.$watch not firing on variable change

I have the following snippet of code below. The problem I'm having is that whenever the value of modal.isOpen is set to true, the $watch statement does not fire. I'm trying to avoid using scope.$apply. What am I doing wrong here...
Inside Link function in an Angular directive:
link: function (scope, elem, attrs) {
scope.$watch('modal.isOpen', function(newValue, oldValue) {
if (newValue)
console.log("This does not trigger...");
}, true);
$document.bind('keydown', function (e) {
if(e.keyCode >= 48 && e.keyCode <= 90) {
scope.modal.isOpen = true;
elem.find('input')[0].focus();
}
..........
});
You should keep watch on property which shouldn't have scope in the string given to $watch function.
scope.$watch('modal.isOpen', function(newValue, oldValue) {
And the while modifying scope from custom event, wouldn't update binding. You need to kick digest cycle using $timeout/$apply() to update binding.(If any code ran ouside of angular context, angular doesn't run digest cycle to update bindings).
$document.bind('keydown', function(e) {
if (e.keyCode >= 48 && e.keyCode <= 90) {
$timeout(function() {
scope.modal.isOpen = true;
elem.find('input')[0].focus();
});
}
..........
});

IE input clear icon sometimes not trigger the change event

I'm using AngularJS in our project and I find IE provides a clear icon on every input box by default. But when I click the 'X' icon the change event won't be fired.
Can someone kindly help me find a simple way to solve this issue?
It worked in plnkr, it's very weird...
$scope.$watch('model.search', function(search){
console.log(search);
}, true);
http://plnkr.co/edit/U8BMJtBnyK1oxviMV9aL?p=preview
I remove all the class and analytics in the input element, it still can not trigger the change...
Thanks in advance!
I would stop worrying about it by hiding this feature-
input::-ms-clear {
display: none;
}
That is just one more of countless non-standard browser features that Microsoft introduce that contain missing functionality.
Our time is too precious. Coding specifically for IE has been a pain for a decade...
I was able to solve this using the following directive, for those looking for an alternative to hiding the clear button. It may not be perfect yet, so I welcome any feedback :)
angular
.module('yourModuleName')
.directive('input', FixIEClearButton);
FixIEClearButton.$inject = ['$timeout', '$sniffer'];
function FixIEClearButton($timeout, $sniffer) {
var directive = {
restrict: 'E',
require: '?ngModel',
link: Link,
controller: function () { }
};
return directive;
function Link(scope, elem, attr, controller) {
var type = elem[0].type;
//ie11 doesn't seem to support the input event, at least according to angular
if (type !== 'text' || !controller || $sniffer.hasEvent('input')) {
return;
}
elem.on("mouseup", function (event) {
var oldValue = elem.val();
if (oldValue == "") {
return;
}
$timeout(function () {
var newValue = elem.val();
if (newValue !== oldValue) {
elem.val(oldValue);
elem.triggerHandler('keydown');
elem.val(newValue);
elem.triggerHandler('focus');
}
}, 0, false);
});
scope.$on('$destroy', destroy);
elem.on('$destroy', destroy);
function destroy() {
elem.off('mouseup');
}
}
}

angularjs ng-blur not working in Chrome or Firefox

I am using ui.bootstrap collapse directive to display drop down menu.
I would like to automatically collapse it when user clicks outside of the div.
When user clicks on Filter button I set focus using:
.directive('setFocus', function () {
return {
restrict: 'A',
scope: {
focusValue: "=setFocus"
},
link: function ($scope, $element, attrs) {
$scope.$watch("focusValue", function (currentValue, previousValue) {
if (currentValue === true && !previousValue) {
$element[0].focus();
console.log('set focus from setFocus directive');
} else if (currentValue === false && previousValue) {
$element[0].blur();
console.log('blurr from setFocus directive');
}
})
}
}
});
HTML
<div collapse="isDropDownCollapsed" class='div2' align-element-right='el1' set-focus='!isDropDownCollapsed' ng-blur="toggleMenu()">
Controller
app.controller('testCtrl', function ($scope) {
$scope.isDropDownCollapsed = true;
$scope.toggleMenu = function () {
$scope.isDropDownCollapsed = !$scope.isDropDownCollapsed;
}
});
It works in IE v11 but focus is also lost when check box is selected.
It doesn't work in Chrome v38 or Firefox v33.1.
example code
In the end I have used this approach:
https://web.archive.org/web/20161104225152/http://vadimpopa.com/onblur-like-for-a-div-in-angularjs-to-close-a-popup/

AngularJS directive for text input: focus on next input on Enter

I would like to implement such a directive for AngularJS: if used in input[text], on hitting enter the focus would move to next input. What would be the best way to accomplish this?
I have a very large form and would like to implement a way to go over the fields in a fast way.
Check this FIDDLE
There is ngKeypress directive in AngularJS, you can read more in here.
If your form is static as you mentioned, easiest way to accomplish what you need is passing next input's id (or index in my example). It's up to you how to provide ids, you can pass entire id or an index.
<input type="text" ng-model="field1" id="f_1"
ng-keypress="keypressHandler($event, 2)"/>
<br/>
<input type="text" ng-model="field2" id="f_2"
ng-keypress="keypressHandler($event, 3)"/>
<br/>
Then in your controller, if key is enter, get element by given id, then focus it.
$scope.keypressHandler = function(event, nextIdx){
if(event.keyCode == 13){
angular.element(
document.querySelector('#f_'+nextIdx))[0].focus();
}
}
As you can see, you can use ng-repeat like that by passing $index instead of hardcoded numbers and creating ids dynamically.
Another solution, use this directive:
angular.module('myApp').directive("nextFocus", nextFocus);
/** Usage:
<input next-focus id="field1">
<input next-focus id="field2">
<input id="field3">
Upon pressing ENTER key the directive will switch focus to
the next field id e.g field2
The last field should not have next-focus directive to avoid
focusing on non-existing element.
Works for Web, iOS (Go button) & Android (Next button) browsers,
**/
function nextFocus() {
var directive = {
restrict: 'A',
link: function(scope, elem, attrs) {
elem.bind('keydown', function(e) {
var partsId = attrs.id.match(/field(\d{1})/);
var currentId = parseInt(partsId[1]);
var code = e.keyCode || e.which;
if (code === 13) {
e.preventDefault();
document.querySelector('#field' + (currentId + 1)).focus();
}
});
}
};
return directive;
}
Related: angularjs move focus to next control on enter
Create a custom directive:
.directive('nextOnEnter', function () {
return {
restrict: 'A',
link: function ($scope, selem, attrs) {
selem.bind('keydown', function (e) {
var code = e.keyCode || e.which;
if (code === 13) {
e.preventDefault();
var pageElems = document.querySelectorAll('input, select, textarea'),
elem = e.srcElement
focusNext = false,
len = pageElems.length;
for (var i = 0; i < len; i++) {
var pe = pageElems[i];
if (focusNext) {
if (pe.style.display !== 'none') {
pe.focus();
break;
}
} else if (pe === e.srcElement) {
focusNext = true;
}
}
}
});
}
}
})
Source: https://stackoverflow.com/a/36960376/717267

Categories