Add action to enter in ember textarea input helper - ember.js

I have used addon ember-autoresize for my textarea to resize my textarea.
{{textarea type="text" placeholder="Comment" value=comment_text autofocus="autofocus" rows=1 max-rows=4 autoresize=true
enter="commentSave"}}
I want to trigger the action when user press enter.But it moves to next line when I press enter.How do I call the action when enter key is pressed in textarea.

Create component called custom-textarea.
in components/custom-textarea.js:
export default Ember.TextArea.extend({
didRender() {
this.$().keypress(function(event) {
if (event.keyCode == 13) {
event.preventDefault();
}
});
}
});
In template, use custom-textarea instead of textarea:
{{custom-textarea type="text" placeholder="Comment" value=comment_text autofocus="autofocus" rows=1 max-rows=4 autoresize=true
enter="commentSave"}}
See WORKING DEMO.
Approach to prevent default behavior taken from this answer.

Related

Set focus on a text box in ember js

I am trying to change a text to a text box. If a user clicks the text, it will change to a test box and so they can edit the content. I have done that. I am able to set the focus by below code.
{{input value=animal.name autofocus=true}}
It only works for the first time. If I focus-out, the text box will again change to text content. If I click the text again, I am able to see the text box, but it is not in focus. Below is the code I am trying.
Component file:
import Ember from 'ember';
export default Ember.Component.extend({
isTextBox: false,
actions: {
editTest() {
this.set('isTextBox', true);
}
},
focusOut() {
this.set('isTextBox', false);
},
});
Template file:
{{yield}}
<center><h2>
<div onclick = {{action 'editTest'}}>
{{#if isTextBox}}
{{input value=animal.name autofocus=true}}
{{else}}
{{animal.name}}
{{/if}}
</div>
</h2></center>
I am new to ember and I trying to do the focus without using jQuery.
Here is the twiddle https://ember-twiddle.com/d832c6540ba94901a6c42d5bb3cfa65e?openFiles=templates.components.text-input.hbs%2Ctemplates.components.text-input.hbs.
You can do this in Plain Old Javascript as follows:
didRender(){
// This works but is not very ember-ish
// document.getElementById('cat-text').focus();
// For a component, you can do this
this.get('element').querySelector("#cat-text").focus();
}
This assumes you have an input like this:
{{input id='cat-text' value=animal.name }}
Ember 2.13+ is no longer dependent on jQuery (although some of the add-ons that you use may be), so you have the possibility of eliminating 35kb (min + gzip) that jQuery would add to the payload of your app.
To expand on kumkanillam's answer you can just set the focus at the end of the render lifecycle if it's rendering a textbox. Since you've only got one text input in your component you can just find it with a selector. No need to worry about using jQuery here that's what it's there for so it is the Ember way.
didRender(){
if(this.get('isTextBox')){
this.$('input[type=text]:first').focus();
}
}
You can provide id to input helper,
{{input id='cat-text' value=animal.name }}
You can make it focus text field for every rendering,
didRender(){
this.$('#cat-text').focus();
}
components/input-text-focused/component.js:
import TextField from '#ember/component/text-field';
export default TextField.extend({
didInsertElement(...args) {
this._super(...args);
const element = this.get('element');
if (element) element.focus();
},
});
{{input-text-focused type="text" name="search" value=search}}

EmberJS How to capture enter key in login form

I'm new to EmberJS/Handlebars and I have a login form that I'd like the user to be able to submit via the enter key. What's the proper way to capture that event and submit my form?
Currently I know 2 ways:
Follow HTML standard.
Use <form> {{input type='submit' action='submitForm'}} </form>.
Remember to use event.preventDefault() in submitForm, or it will redirect to form's action property (or refresh current page if you didn't set any).
Use keydown/keyup event in every form elements that you want to trigger enter (well, this is really a bad idea, but it works):
Template.hbs
{{input type='textbox' key-up='submitForm'}}
Controller.js
export default Ember.Controller.extend({
actions: {
submitForm(value, event) {
if (event.keyCode === 13) {
// Do something here
}
}
}
});
Answering my own question. Here's what I did:
I found a handlebars attribute insert-newline='[functionCall]' that filters the enter key.

Prevent click into {{input}} component from propagating/bubbling up (ember)

I have an {{input}} inside of an element that itself has an action.
How do I prevent clicking into the input from triggering the click event on the parent element?
I have tried bubbles=false.
I have also tried extending {{input}} and in the extended input I caught the click event and called event.preventDefault()
Please try my test case: https://ember-twiddle.com/a2cee9abd63a7400124e2745a7820cf8?numColumns=2&openFiles=controllers.application.js%2Ctemplates.application.hbs
Example hbs:
<div {{action "alert"}}>
I don't want the click into the input to trigger the div's onlick. Help!<br/>
{{input bubbles=false}}
</div>
Define component say my-input which extends Ember.TextField and define click function and return false to prevent bubbling.
import Ember from 'ember';
export default Ember.TextField.extend({
click(){
console.log('click my input');
return false;
}
});
For my-input component, you dont need to define anything to handle click event while including the component. you can just say {{my-input }}
Here is the working twiddle

sending actions from within a component in Ember

I'm trying to figure out how to handle in a single place a "login" action, that must be activated from a button click and "enter" keypress;
in my template I've wrapped everything inside a "login-functions" component
//template home.hbs
{{#login-functions}}
<input id="email" type="email" class="validate">
<input id="password" type="password" class="validate">
<div id="login" {{action "login"}}>
{{/login-functions}}
//component components/login-functions.js
export default Ember.Component.extend({
actions: {
login: function() {
var email = $('#email').val();
var password = $('#password').val();
var self = this;
Utils.login(email, password).done(function(res) {
localStorage.setItem('Access-Token', res.data.token);
localStorage.setItem('userId', res.data.user_id);
self.transitionToRoute('feed');
})
.error(function(error) {
//handle error
});
}
},
keyPress: function(event) {
if (event.charCode === 13) {
console.log('login attempt');
this.send('login');
}
}
});
But this doesn't work because the action is not sent from the template button to the component's action and also because from the component I can't perform the transition.
Can someone tell the best way to handle this?
I think it's because your button is part of your home template. Maybe the form should be moved in your login-functions template and be called from your home template by doing {{login-functions}}.
And for the redirection, components can't do them, I'd suggest to call an action using this.sendAction('didLogin') and handle the redirection in your HomeController.
Move the keyPress functions out of the actions.
Updated --- Here is a working demo

Ember extend input helper so that I can add a class whenever the html5 invalid event fires

In a non Ember world I could put this in my document ready:
$("input").on("invalid", function(event) {
$(this).addClass('isDirty');
});
And then I would know that whenever a form is submitted, it would inturn fire the invalid event on invalid inputs and allow me to mark them as dirty for css purposes. I tried to do this in Ember in a component (in didInsertElement):
export default Ember.Component.extend({
didInsertElement: function() {
this.$('input, textarea').on('invalid', function() {
console.log('worked!');
Ember.$(this).addClass('isDirty');
});
},
actions: {
keyDownAction: function(value, event) {
// Mark input/textarea as dirty
Ember.run(() => {
this.$('input, textarea').addClass('isDirty');
})
if (this.get('keyDown')) {
this.sendAction('keyDown', value, event);
}
},
focusInAction: function(value, event) {
if (this.get('focusIn')) {
this.sendAction('focusIn', value, event);
}
},
focusOutAction: function(value, event) {
// Mark input/textarea as dirty
Ember.run(() => {
this.$('input, textarea').addClass('isDirty');
})
if (this.get('focusOut')) {
this.sendAction('focusOut', value, event);
}
}
}
})
hbs:
{{input type=type value=value id=inputId class=inputClass name=name tabindex=tabindex autofocus=autofocus required=required list=list
min=min max=max step=step
key-down="keyDownAction" focus-in="focusInAction" focus-out="focusOutAction"}}
<span class="bar"></span>
<label class="{{if value 'text-present'}}">{{placeholder}}</label>
But my event isn't firing. Can I attach the ember input helper to the html5 invalid event?
It works for me. You just need to make sure you wrap both component and submit button (for example, <button type='submit'>Submit</button>) in <form> element.
For example, template:
<form>
{{my-component type='text' required='true' placeholder='My field'}}
<button type='submit'>Submit</button>
</form>
Clicking submit button without <form> will do nothing. Clicking submit button when both elements are inside <form> will log worked! in console, add class isDirty to <input> and display native browser dialog to fill this field.
Working demo.
Full code behind demo.
It looks like you're doing things way too complicated. from what i understand is you're marking a textarea's validty depending on its value.
Lets say you have a text area
{{textarea value=textValue class="form-control"}}
And this input is supposed to have value for validity.
textAreIsValid: function() {
return !Ember.isEmpty(this.get('textValue'); // meaning the text can't be empty.
}.property('textValue')
To show its validity you to user, i would wrap the text area like this
<div class="control-group {{if textAreIsValid 'valid-class' 'has-error'}}">
XX text area XX
</div>
Also instead of keyPres and up you could be observing the value
areaValueChanged: function() {
}.observes('textValue'),
It turns out that adding an Ember action to the submit button, such as:
<button type="submit" {{action 'testAction'}}>Go</button>
And returning false from the action, was not enough.
I did try adding preventDefault=false to the button, which worked in that the invalid event fired, but didnt work in that the whole page then submited rather than Ember handling things
The best solution therefore was to call this.$('form')[0].checkValidity(); just before returning false in the action, i.e.
if (formIsInvalid) {
this.$('form')[0].checkValidity();
return false;
}
Example twiddle now working: https://ember-twiddle.com/13af9d78ff5007626960