How to automatically focus first backbone-forms input field? - backbone.js

The following screenshot shows a combined form for sign-in and sign-up:
The following module is used to render the AuthView:
MyApp.module("User", function(User, App, Backbone, Marionette, $, _) {
User.AuthView = Marionette.ItemView.extend({
className: "reveal-modal",
template: "user/auth",
ui: {
signInForm: "#signin-form",
signUpForm: "#signup-form"
},
events: {
"focus input": "onFocus"
},
onFocus: function() {
console.log("Some input field has received focus.");
},
onRender: function() {
this.signInForm = new Backbone.Form({
schema: {
signInEmail: {
type: "Text",
title: "E-Mail address"
},
signInPassword: {
type: "Password",
title: "Password"
}
}
}).render();
this.ui.signInForm.prepend(this.signInForm.el);
this.signUpForm = new Backbone.Form({
schema: {
signUpEmail: {
type: "Text",
title: "E-Mail address"
},
signUpPassword: {
type: "Password",
title: "Password"
},
signUpPasswordConfirmation: {
type: "Password",
title: "Password confirmation"
}
}
}).render();
this.ui.signUpForm.prepend(this.signUpForm.el);
}
});
});
How can I automatically focus the first field in each sub-form whenever it is rendered? The first fields would be signInEmail for the signInForm and signUpEmail for the signUpForm.
I tried to listen to focus input events. Such an event is triggered when I click into one of the input fields, not before.
Meanwhile, inspired by the current answers I came up with the following helper function:
focusFirstFormField: function(form) {
if (_.isUndefined(form)) {
throw "IllegalStateException: Form is undefined."
}
// TODO: AuthView does not focus first sign-in field.
var firstInput = form.find(':input:first');
if (_.isObject(firstInput)) {
if (firstInput.length > 0) {
firstInput = firstInput[0];
}
else {
throw "IllegalStateException: Form find returns an empty jQuery object."
}
}
_.defer(function() {
firstInput.focus();
});
}
There is still need for improvement, though.

The events object are DOM events which are generally triggered by the user so that's not what you'll likely want to use in this case.
If I'm understanding you correctly you would like to put the focus in the first input of each of the forms but since you can only have focus on one thing at a time and they are rendering together you'll have to choose one or the other.
The simplest option is to add another line at the end of onRender focusing on the input. If your input is generating an input something like this:
<input type="text" name="signInEmail">
Then you can add:
this.$('[name=signInEmail]').focus();
If not you'll have to change the selector this.$(xxxx).focus() to suit.

You can use onDomRefresh event of the view. It will be triggered after view rendered and Dom refreshed.
onDomRefresh: function() {
this.focusFirstInput();
};
focusFirstInput: function() {
this.$(':input:visible:enabled:first').focus();
};
This solution applies to general cases. However, pay attention if you are using Bootstrap. I can't get this work there. Instead, I set autofocus: 'autofocus' in the field and it works.

You can add it to onRender method.
this.ui.signInForm.find('input[type=text]:first').focus();
this.ui.signUpForm.find('input[type=text]:first').focus();

On the onRender method I do :
$(this.el).find(':input[autofocus]').focus();
And I add the autofocus="" flag onto my HTML node. This works for refresh.

Related

AlertInput handler never gets called

I'm using Ionic 4 with React and typescript.
I'm looking to create an alert with a email input and 2 buttons, "cancel" and "accept".
I want the "accept" button to only be available when the user is giving a valid email address. Therefore I want to use a regex in the input field handler, but the handler is never called, not when typing nor when pressing enter. How can I get it to get callled when the user is typing
async showAlert() {
var promise = await alertController.create({
header: "Recevez la photo dans votre boƮte mail",
inputs: [{
name: "email",
type: "email",
placeholder: "email",
handler: () => {
console.log("input Fild Hanlder Called");
}
}],
buttons: [{
text: "cancel",
role: "cancel",
handler: cancel => {
console.log("cancel");
}
},
{
text: "envoyer photo",
role: "send",
handler: (alertData) => {
console.log((/^[a-zA-Z0-9]+#[a-zA-Z0-9]+\.[A-Za-z]+$/.test((alertData.email))));
}
}
]
});
await promise.present();
let result = await promise.onDidDismiss();
}
tl;tr This feature is not implemented in ionic4: ionic/issues/19059
After comparing the ionic code for rendering a checkbox in an alert and any other input element I came to the sad conclusion that the feature you are looking for doesn't exist.
At the moment it looks like handler on input in alerts is only supported for checkboxes and radio-inputs
There was a PR for ionic3 that added the validators option to AlertInputs to provide angular form validation but its not there anymore in ionic4.
There is still an open issue for ionic3 requesting input validation for alert inputs but non for ionic4 as far as I can see.
Update: new feature request for ionic4

Properties not changing on the DOM after a GET request

I am working on a component to render user details. The details are fetched from an API request and properties are updated but these changes are not reflected on the DOM.
The company I work for is still using Polymer 1.2 and I am having difficulty finding and understanding the documentation. Do I need to make the get request from the parent component or is it possible to do this directly inside the component? There is something fundamental I am not grasping about this and wondering if someone could shed some light on it for me.
Thank you.
Snippet from the template:
<p>{{i18n.GLOBAL_USERNAME}} - [[username]]</p>
<p>{{i18n.GLOBAL_FIRSTNAME}} - [[firstname]]</p>
<p>{{i18n.GLOBAL_LASTNAME}} - [[lastname]]</p>
<p>{{i18n.GLOBAL_EMAIL}} - [[email]]</p>
<p>{{i18n.GLOBAL_NUMBER}} - [[number]]</p>
Snippet from the polymer functions:
Polymer({
is: 'my-component',
properties: {
username: {
type: String,
value: "n/a",
},
firstname: {
type: String,
value: "n/a"
},
lastname: {
type: String,
value: "n/a"
},
email: {
type: String,
value: "n/a"
},
number: {
type: String,
value: "n/a"
},
},
ready: function () {
var user = app.auth.hasSession()
if (user !== null) {
app.getUserInfo(user.user_id, this._getUserSuccessful, this._getUserFail);
}
},
_getUserSuccessful: function (res) {
this.username = res.user.user_id
this.firstname = res.user.firstname
this.lastname = res.user.lastname
this.email = res.user.email
this.number = res.user.phone_number
console.log("got user details")
},
_getUserFail: function () {
console.log("failed to get user details")
},
});
You need to use Polymer setter methods instead of plain assignment.
Here's an example:
_getUserSuccessful: function (res) {
this.set('username', res.user.user_id)
this.set('firstname', res.user.firstname)
this.set('lastname', res.user.lastname)
this.set('email', res.user.email)
this.set('number', res.user.number)
console.log("got user details")
},
Using setter and/or array mutator methods is required for data-bound properties otherwise Polymer can't know that something has changed in order to update the bindings.
I'd really suggest you read the whole Data system concepts article before moving forward with doing any kind of work with Polymer 1.x.

use Dojo to programmatically set checkboxes checked

The codes below returns Uncaught TypeError: Cannot set property 'checked' of null.
what is the correct way to programmatic set checkbox as checked?
array.forEach(this._getAllCheckBoxIDs(), function(item){
dom.byId(item).checked = true;
}, this);
The following example shows a programmatic example on how to set property checked for a widget checkbox.
The script gets references of your checkboxes using dijit/registry opposite to querying the DOM.
Instead of setting a property directly for your widget like this:
dom.byId(item).checked = true;
I would suggest using a setter like:
widgetReference.set('checked', true);
This will allow the widget life-cycle to work properly.
Live example here:
https://jsfiddle.net/femtf4uh/
require(["dijit/form/CheckBox", "dijit/registry", "dijit/form/Button", "dojo/domReady!"], function(CheckBox, registry, Button) {
new CheckBox({
id: "checkBox0",
name: "checkBox0",
value: "option0",
checked: false,
onChange: function(event) {
}
}, "checkBox0").startup();
new CheckBox({
id: "checkBox1",
name: "checkBox1",
value: "option1",
checked: false,
onChange: function(event) {
}
}, "checkBox1").startup();
var markCheckAll = function() {
registry.toArray().forEach(function(widget) {
if (widget.type === 'checkbox'){
widget.set('checked', true);
}
});
};
markCheckAll();
});
<input id="checkBox0" />
<label for="checkBox">Option 0</label>
<br>
<input id="checkBox1" />
<label for="checkBox">Option 1</label>
<br>
Well, If you you have the collections of dojo checkboxes then I would suggest you to use registry.byId instead of dojo.byId because you need checkbox dojo widget along with it's domNode to update its attribute.
dojo class name:-
dijit/registry
Ex:-
// require registry class first
array.forEach(this._getAllCheckBoxIDs(), function(item){
registry.byId(item).set("checked", true);
}, this);
for more details please click here...
Hoping this will help you :)

Sencha Touch 2.3: Remove validations from hidden form fields

I am doing form validations in Sencha Touch 2.3. My model looks like following.
Ext.define('net.omobio.dialog.dialogcc.model.StockTransferDetails', {
extend: 'Ext.data.Model',
config: {
fields: ['to_msisdn','to_profile_id','transfer_lob','transfer_item_status','transfer_product','transfer_qty','transfer_req_type','transfer_item_type','transfer_pack_type'],
validations: [
{ type: 'presence', field: 'to_msisdn' },
{ type: 'presence', field: 'to_profile_id' },
{ type: 'exclusion', field: 'transfer_lob', list: ['null'] },
{ type: 'exclusion', field: 'transfer_req_type', list: ['null'] },
{ type: 'exclusion', field: 'transfer_item_type', list: ['null'] },
{ type: 'exclusion', field: 'transfer_pack_type', list: ['null'] }
]
}
});
Following is a code segment that I use in my controller to remove validations from hidden form fields but no luck.
var form1 = me.getStockTransferRequestPage();
var model = Ext.create("net.omobio.dialog.dialogcc.model.StockTransferDetails", form1.getValues());
// validate form fields
var errors = model.validate();
if (!errors.isValid()) {
// loop through validation errors and generate a message to the user
errors.each(function (errorObj){
//errorString += errorObj.getField() + " " + errorObj.getMessage();
console.log('7777777777777777777 '+errorObj.getField());
if (!Ext.getCmp(errorObj.getField().toString()).isHidden()) {
var s = Ext.String.format('field[name={0}]',errorObj.getField());
form1.down(s).addCls('invalidField');
}
});
Ext.Msg.alert('','stock_transfer.errors.required_fields_empty');
}
I would be much appreciated if anyone could help me to solve this.
Thank you
so there are multiple ways to achieve this, my preference even though some folks won't like it, but it will always work.
I did the following override to solve this problem, tried my best not to affect the normal flow of validation.the first two overrides have to be added somewhere to your overrides folder, you only have to add them once for the whole app.
Ext.Define('Ext.form.field.BaseOverride', {
override: 'Ext.form.field,Base',
/* traverse up and look for a hidden Parent/Ancestor */
isParentHidden: function () {
return this.up('[hidden=true]');
}
/* override isValid basic method to consider skipValidateWhenHidden property, when skipValidateWhenHidden is set to true code should check if the elementor it's Parent/Ancestors is hidden */
isValid: function () {
var me = this,
disabled = me.disabled,
isHidden = me.isHidden(),
skipValidateWhenHidden = !!me.skipValidateWhenHidden,
validate = me.forceValidation || !disabled,
isValid = validate ? me.validateValue(me.processRawValue(me.getRawValue())) : disabled;
if (isValid || !skipValidateWhenHidden) {
return isValid;
}
if (skipValidateWhenHidden) {
isHidden = isHidden ? true : me.isParentHidden();
if (isHidden) {
return skipValidateWhenHidden;
}
}
return isValid;
}
});
and eventually you'll be able to do the following, which is set the property to true on any field so if its not visible for the user, it will survive validation
{
itemId: 'City',
cls: 'AddressCity',
xtype: 'textfield',
emptyText: emptyCityText,
skipValidateWhenHidden: true,
},
another approach is to add a show()/Hide() listener on the fields container to enable/disable the children, disabling the fields would make them skip validation, but i'm not a big fan of managing button states and wiring listeners.
Note
Ext.getCmp() takes component id
errorObj.getField().toString() returns model field name, It won't
return id of the component (hidden) field.
So if model field name matches with hidden field id, It will work. Otherwise it won't work.

Adding click event to radio boxes Ext.form.Radio in Ext JS

I have a simple radio button:
new Ext.form.Radio({
id: 'ptype',
boxLabel:'Yes',
name: 'price_type',
value: 1
})
However Im having trouble adding a on click event ot it.
I usually use:
listeners: {
click: function (a,e) {
//event
}
}
As a config parameter, however it does not seem to work in this case.
Any advice appreciated, thanks.
Radio and checkboxes do not have a click event -- I believe you want the check event instead. Your listener should look like:
listeners: {
check: function (ctl, val) {
// val is the new checked boolean value
}
}
Note that the handler config is a handy shortcut for this (also available on buttons). Instead of the listeners syntax you could just do this:
handler: function(ctl, val) {
// etc
}
Try this:
new Ext.form.Radio({
id: 'ptype',
boxLabel:'Yes',
name: 'price_type',
value: 1
onClick: function(e){
.....
.....
}
})
If you're using a CheckBoxGroup, you should do something like this to make sure you are firing on the correct Radio.
listeners: {
check: function(checkbox, checked) {
if(checked) {
// do whatever.
}
}
}

Resources