How to catch a return on an input element using Aurelia?
Asked Answered
G

4

9

In angularjs I had the following:

app.directive('ngEnter', function () {
   return function (scope, element, attrs) {
    element.bind("keydown keypress", function (event) {
        if(event.which === 13) {
            scope.$apply(function (){
                scope.$eval(attrs.ngEnter);
            });

            event.preventDefault();
        }
    });
  };
});

And the html was:

<input type="text" ng-model="searchText" class="form-control"
                               placeholder="Search"
                               ng-enter="search($event, searchText)">

So basically once I have finished typing my text to search on, when I pressed the enter key the search function on my controller would run.

How would I do this in Aurelia?

I am still learning about its features so any help would be appreciated.

Gad answered 17/4, 2015 at 2:22 Comment(1)
I believe tagging as angularjs is invalid because you want to perform something on another framework. And one is not required to know angularjs to answer this question.Alvar
K
20

I think an alternative to the angular ngEnter would be:

import {customAttribute, inject} from 'aurelia-framework';

@customAttribute('enter-press')
@inject(Element)
export class EnterPress {
    element: Element;
    value: Function;
    enterPressed: (e: KeyboardEvent) => void;

    constructor(element) {
        this.element = element;

        this.enterPressed = e => {
            let key = e.which || e.keyCode;
            if (key === 13) {
                this.value();//'this' won't be changed so you have access to you VM properties in 'called' method
            }
        };
    }

    attached() {
        this.element.addEventListener('keypress', this.enterPressed);
    }

    detached() {
        this.element.removeEventListener('keypress', this.enterPressed);
    }
}
<input type="password" enter-press.call="signIn()"/>
Kristofer answered 19/7, 2016 at 14:50 Comment(2)
Very very nice answer. Thanks Kamil. I am also using this solution for detecting ctrl+enter press on my textarea. Which key code is 10.Noah
This is the best solution and should be marked as the answer.Extremism
R
18

The simplest way would be to wrap the input in a form element and bind to the submit event of the form.

<form role="form" submit.delegate="search()">
  <div class="form-group">
    <label for="searchText">Search:</label>
    <input type="text" value.bind="searchText" 
           class="form-control" id="searchText" 
           placeholder="Search">
  </div>
  <button type="submit" class="btn btn-default">Submit</button>
</form>

This will give you the same behavior you have built above. I'm still working to create an example of a custom attribute to do this, but honestly, this is how I would recommend you do this specific thing (capturing when the user presses enter).

Roderica answered 17/4, 2015 at 12:53 Comment(5)
this is absolutely the way to do this. wrapping in a form will enable all sorts of other desired behaviors, including optional reset buttons.Morgen
This doesn't seem to work when you have multiple buttons (at least not in Chrome, anyway). It also will not work if you want to bind the enter keypress inside of one form to different actions depending on where exactly they are in the form.Viscera
+1 to this. I had a similar scenario a few days back, and as soon as I wrapped it in a form tag (Which let's be honest, you should be doing anyway if your generating correct semantic HTML5 code) not only did I get my return back, but my tab functionality started working again, and it helped make aurelia-auth work better for validation.Seriema
I had this exact code, except I noticed the button click validated correctly but enter would by pass it. The Search() function needs to test the validation, like this: search() { this.controller.validate().then(result => { if (result.valid) { ...I originally had validate().then() =>... Also, if "test--" is invalid in a search textbox because of the "--" you also want to test the route that it will direct to, meaning you can't do something like this directly: localhost:9000/#/list?searchTitle=test--Douala
The answer from @Kamil is the best and most general solution.Extremism
V
4

This does not seem to be supported out of the box. While not perfect, here is what I intend to do:

  • Add a hidden submit button at the top of my form with a click.delegate attribute.
  • Run some code in my VM when its clicked. This code will decide what to do with the enter keypress based on any custom logic I need.

Hope that helps, Andrew

EDIT:

You could also add a keypress event delegate:

<input keypress.delegate="doSomething($event)" />

And define doSomething() as:

doSomething(event) {
  if(event.which == 13) {
    alert('Your code goes here!');
  }
  event.preventDefault();
}

This will be a little cleaner when you have many inputs with differing enter keypress behaviours.

Viscera answered 10/9, 2015 at 18:25 Comment(1)
keypress.delegate and keypress.trigger in an <input> block entering textSita
H
4

Because of keypress.delegate and keypress.trigger in an <input> block entering text by default, your function must return true to avoid it, like this:

doSomething(event) {
    if(event.which == 13) {
        console.log('Your code goes here!');
        event.preventDefault();
        return false;
    }
    return true;
}
Hypersonic answered 15/12, 2017 at 15:21 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.