Enter key enable using knockout and javascript function - javascript

i have an html textbox with onkeypress event to send message like below
<input type="text" data-bind="attr:{id: 'txtDim' + $data.userID, onkeypress: $root.sendMsg('#txtDim' + $data.userID, $data)}" />
I have written javascript function to to send message while preesing enter button like below:
self.sendMsg = function (id, data) {
$(id).keydown(function (e) {
if (e.which == 13) {
//method called to send message
//self.SendDIM(data);
}
});
};
In my case i have to press enter button 2 times to send the message.
1: keypress call self.sendMsg
2: keypress call self.SendDIM
But i need to send message on one keypress only. It can be done in plain javascript only. But i need viewmodel data, so applied in data-bind. So not working fine.

The reason you need to press enter twice is that your sendMsg method is only attaching a handler to the keydown event. This handler is then invoked on the second button press.
A better approach would be to write a custom binding handler that attaches the event handler and passes the view model through:
ko.bindingHandlers.returnAction = {
init: function(element, valueAccessor, allBindingsAccessor, viewModel) {
var value = ko.utils.unwrapObservable(valueAccessor());
$(element).keydown(function(e) {
if (e.which === 13) {
value(viewModel);
}
});
}
};
You can see a running example here

I have added keypress event like below to textbox
<input type="text" data-bind="attr:{id: 'txtGoalsheetNote' + $data.userID}, event:{keypress: $root.SendMsg}" />
And in javascript i have added the following method by keeping event as a parameter
self.SendMsg= function (data, event) {
try {
if (event.which == 13) {
//call method here
return false;
}
return true;
}
catch (e)
{ }
}
Then its work.

Related

To call login function Only once after pressing 'enter' key

I'm working on a login function right now. I put my enterKey function in the input, and my aim is to call the login function when the user press the enter key. It works fine if there's nothing in the input area, however, I find that if I have some characters in the input text area, the function will be called multiple times and give multiple error messages.
For example, if I have N characters in the input, I will receive (N+1) error messages after press the enter key.
Here is my code:
enterKeyPress() {
window.addEventListener("keypress", e => {
if (e.keyCode === 13) {
console.log('enter key pressed!'); // I will receive this msg (N+1) times when there're N characters in the input text area
e.preventDefault();
this.loginUser(); // this is the login function I want to call after press enter key, but just once per press
}
});
}
render() {
return(
<Input
type="password"
placeholder="Password"
onChange={e =>
this.setState({ password: e.target.value })
}
onKeyPress={this.enterKeyPress()}
/>
);
}
Can anyone help me with this?
Event listeners aren't necessary in this case.
First thing, adjust enterKeyPress to not create an event listener. If you haven't bound the function in your constructor, then you can convert enterKeyPress to an arrow function:
enterKeyPress = (e) => {
if (e.keyCode === 13) {
console.log('enter key pressed!');
e.preventDefault();
this.loginUser();
});
}
Converting enterKeyPress to an arrow function is one way to scope the function to the component. Another option is binding the function in your constructor or in your render function, which is well documented elsewhere. If you've already bound the function in your constructor (you haven't included it here), then you can ignore that part.
Second, adjust your onKeyPress prop to pass the function rather than calling it:
<Input
type="password"
placeholder="Password"
onChange={e =>
this.setState({ password: e.target.value })
}
onKeyPress={this.enterKeyPress}
/>
It's also worth noting that there's another general JavaScript mistake here: using an anonymous callback function in your event listener. By using an anonymous function, you're enabling the same function to be added multiple times, since a different function reference is generated each time. This also means that you won't be able to remove it later, since you'll require the function reference to do so.
Again, you don't need an event listener here, but if you did, you should probably define the callback in the component scope, so that you can remove it at some later point. A common pattern for using event listeners is as follows:
handleKeyPress = (e) => {
if (e.keyCode === 13) {
console.log('enter key pressed!');
e.preventDefault();
this.loginUser();
});
}
componentDidMount() {
window.addEventListener("keypress", this.handleKeyPress);
}
componentWillUnmount() {
window.removeEventListener("keypress", this.handleKeyPress);
}
From some quick Googling, I think this might do what you need:
enterKeyPress(e) {
if (e.keyCode === 13) {
console.log('enter key pressed!'); // I will receive this msg (N+1) times when there're N characters in the input text area
e.preventDefault();
this.loginUser(); // this is the login function I want to call after press enter key, but just once per press
});
}
render() {
return(
<Input
type="password"
placeholder="Password"
onChange={e =>
this.setState({ password: e.target.value })
}
onKeyPress={this.enterKeyPress}
/>
);
}
onKeyPress already does what the event listener you're trying to add does, so just pass it the keypress event directly instead.
Like #Ronnie has pointed out in the comments, you are adding a new event listener every time the onKeyPress function is triggered on the component, which causes the problems. Since onKeyPress event already passes the event as an argument (similar to onClick event), you can access the keyCode from there.
You can change your enterKeyPress function to the following:
enterKeyPress(e) {
if (e.keyCode === 13) {
console.log('enter key pressed!');
e.preventDefault();
this.loginUser();
}
}

How to execute Angular ng-click directive inside custom component on enter key press

I have a custom icon component using isolate scope where a user can define what he or she wants to happen on ng-click:
<ers-icon name="history" ng-click="ctrl.clickAlert('history')"></ers-icon>
This calls a method from within the user's controller as follows:
this.clickAlert = function (icon) {
alert("You selected the " + icon + " icon.");
}
I need to add enter key functionality to the icon component without adding any other code, from I have above, to my html element. So essentially listen for the enter key press from within the directive and evaluate the ng-click directive on ers-icon. Here is what I have as the icon directive:
// on click works fine
.on("click", (event:JQueryEventObject):void => {
if (this.ngDisabled) {
event.preventDefault();
event.stopPropagation();
}
});
}
//execute whatever function is specified inside ng-click on enter key press
.on("keydown", (event:JQueryEventObject):void => {
if (event.keyCode === 13) {
if (this.ngDisabled) {
event.preventDefault();
event.stopPropagation();
} else {
// need to execute ng-click here
// this try doesn't work, gives me undefined
$scope.$apply(() => {
$scope.$eval($attr.ngClick);
}
}
}
});
This runs fine on enter key press but I can't get the controller function defined on ng-click to run.
I thought maybe $eval or $parse would work but it looks like those will only evaluate expressions within {{}}. What is the best way to execute that ng-click attribute so that when a user hits the enter key, the "this.clickAlert" function is ran and an alert is shown on the screen?
I can't really change any of the code as is above, just looking for the solution within the else statement of the on keydown listener.
I solved it this way:
.on("keydown", (event:JQueryEventObject):void => {
if (event.keyCode === 13) {
if (this.ngDisabled) {
event.preventDefault();
event.stopPropagation();
} else {
// need to execute ng-click here
this.element.trigger("click");
}
}
});

Simulate enter-key in form field and preserve other handlers

We're trying to make a generic approach for a piece of software we are developing that ties into form fields.
So far so good but we're running in to an edge case that prevents submitting a form/field that has another handler tied in to it.
Here's the (condensed) use case:
HTML:
<form id="form1">
<input type=field id="field1"/>
</form>
click to submit
Normal behaviour is that when a user types 'foo' into the field and hits enter, the form is handled and submitted to the correct 'endpoint' which isn't necessarily the defined one in the form's opening tag. There could be some function (from somewhere else) that handles this enter-event.
Unfortunately, we can't predict what that function is, we like to keep it generic.
In the above HTML, clicking on the link should trigger an enter-event on the form field that mimics the browser/user behaviour and thus some unknown handler.
This is our Javscript (we're using jquery):
$('#field1').keypress(function (event) {
if (event.which == 13) {
console.log("enter pressed");
//return false; only if needed
}
});
$( "#link" ).click(function() {
var e = jQuery.Event('keypress');
e.which = 13; // #13 = Enter key
$("#field1").focus();
$("#field1").trigger(e);
})
When entering 'foo' in the field and pressing enter the form gets submitted. But when we click the link we do a focus() and then firing the key-event but the form isn't submitted.
We can't use a submit() because of the unknown handlers.
Try the code here: http://codepen.io/conversify/pen/yOjQob
What happens when enter key is pressed is, if the input is inside a form, the form is submitted. This is the default behavior. When you simulate a key press, you should do the same, unless the default behavior is prevented.
$('#field1').keypress(function (event) {
if (event.which == 13) {
console.log("enter pressed");
// event.preventDefault(); if needed
}
});
$( "#link" ).click(function() {
var e = jQuery.Event('keypress');
e.which = 13; // #13 = Enter key
$("#field1").focus();
$("#field1").trigger(e);
var form=$("#field1").closest("form");
if(form&&!e.isDefaultPrevented()) form.submit();
})
Now you can pass your event object to the handlers and they can prevent the submit if they want so, or you can prevent it in your keypress handler.
You should separate out the form handler from the enter and click handlers.
var formHandler = function(e) {
// ... code to submit form ...
console.log("form handled");
};
Then set your keypress handler like this:
$('#field1').keypress(function (event) {
if (event.which == 13) {
formHandler();
}
});
And your click handler like this:
$( "#link" ).click(function() {
formHandler();
});
You can unbind the unknown handlers using unbind('submit') and then use submit() like following.
$("#link").click(function () {
$("#form1").unbind('submit').submit();
});

Binding input enter to function call using knockout

I'm trying to have an input element call a function when I press enter and use the value in the element:
<input id="searchQuery" placeholder="Search..." type="text" data-bind="value: searchQuery, valueUpdate: 'onkeydown', event: { keydown: searchQueryEntered }"/>
The function:
searchQueryEntered = function (value, event) {
if (event.keyCode == 13)
...do some stuff...
},
My function does get called, but searchQuery is never updated! I can't even type anything into the input. Somehow it's getting thrown out. What I'm trying to do seems pretty simple to me but I haven't been able to get it right.
To fix your input you need to return true from your keydown handler:
searchQueryEntered = function (value, event) {
if (event.keyCode == 13) {
...do some stuff...
}
return true;
}
Then you should use valueUpdate: 'afterkeydown' to make your model be updated after each keydown.
Check out this working example: http://jsfiddle.net/tabalinas/h4u8E/
Register a bindinghandler for the enter key
ko.bindingHandlers.onEnterKey = {
init: function(element, valueAccessor, allBindings, vm) {
ko.utils.registerEventHandler(element, "keyup", function(event) {
if (event.keyCode === 13) {
ko.utils.triggerEvent(element, "change");
valueAccessor().call(vm, vm);
}
return true;
});
}
};
then you can bind as follow onEnterKey: searchQueryEntered
see fiddle below
http://jsfiddle.net/NccZ8/2/

calling javascript method on onclick and onkeypress events

I have a search box and search button. I want to call a javascript method in case somebody types in search box and hits enter or clicks on search button.
So far with keypress event it's working fine:
function Search(e) {
if(e.keyCode==13) {
//DO operation
}
}
If I want to call same function on onclick event of search button, how can I use same method shown above. Only purpose here is not to duplicate same code by writing two different methods which at the end do same thing.
Add listeners to both events (onclick and onkeypress) and use event's type:
function Search(e) {
if( e.type == 'click' ||
(e.type=='keypress' && e.keyCode==13) ){
//DO operation
}
}
Demo here.
function Search(e) {
var doOper = function() {
//DO operation
}
if(e.keyCode==13) {
doOper();
}
if(buttonClicked) {
doOper();
}
}

Categories