How can I add an own-form validator in extjs 6.2.0 modern application? In classic:
validator : function(value){
//do something
}
This surely depends on what you want, but for example what I did recently was adding validator using binding with a ViewModel (seems to work in both classic and modern toolkits). This sure may be overcomplicated for your needs, but it looks like ViewModel's binding with formula suits well for email validation.
Form:
Ext.define('App.login.LoginForm', {
extend: 'Ext.form.Panel',
requires: [ 'App.login.LoginModel' ],
viewModel: {
type: 'login' // references alias "viewmodel.login"
},
layout: 'vbox',
defaultType: 'textfield',
items: [{
name: 'login',
itemId: 'login-fld',
bind: '{credentials.login}'
},{
inputType: 'password',
name: 'password',
bind: '{credentials.password}'
},{
xtype: 'button',
text: 'Submit',
action: 'save',
bind: {
disabled: '{!isCredentialsOk}'
}
}]
});
ViewModel:
Ext.define("App.login.LoginViewModel", {
extend: "Ext.app.ViewModel",
alias: 'viewmodel.login',
links: {
credentials: {
reference: 'App.login.LoginModel',
create: true
}
},
formulas: {
isCredentialsOk: function (get) {
return Boolean(get('credentials.login') && get('credentials.password'));
}
}
});
Model:
Ext.define('App.login.LoginModel', {
extend: 'Ext.data.Model',
fields: [
{ name: 'login', type: 'string', allowBlank: false },
{ name: 'password', type: 'string', allowBlank: false }
],
validators: [
{ field: 'login', type: 'presence', message: 'Login empty' },
{ field: 'password', type: 'presence', message: 'Password empty' }
]
});
Related
I have 4 forms, which called to the main view by buttons through controller.
How I must to link fields of forms with Django database, through REST api?
For example I have form:
Ext.define('Foresto.view.forms.RenterData', {
extend: 'Ext.form.Panel',
title: 'Renter',
header: {
cls: 'header-cls'
},
xtype: 'foresto-renterdata',
layout: 'fit',
scrollable: true,
tools: [{
type: 'minimize',
handler: function() {
this.up("panel").hide();
}
}, {
type: 'save'
}, {
type: 'close',
handler: function() {
this.up("panel").close();
}
}],
requires: ['Foresto.view.forms.RenterType'],
url: 'save-form.php',
defaults: {
xtype: 'textfield',
labelWrap: true,
required: true,
afterLabelTextTpl: [
'<span style="color:red;font-weight:normal" data-qtip="Required">*</span>'
]
},
items: [{
xtype: 'foresto-rentertype',
label: 'Type',
name: 'rentertype'
}, {
xtype: 'selectfield',
label: 'Document',
name: 'document',
}, {
label: 'Document number',
name: 'document_num'
}, {
label: 'NAME',
name: 'name_represent'
}, {
label: 'Position',
name: 'position_represent'
}]
});
And values of
name: 'document'
From Django:
{"license","rent agreement","order", "ticket"}
Where I can to add api url? I have to create proxy store or I can add api into form?
Please help! thanks!
I have a grid with a pagination. When I set a filter, the ajax request is successfully executed, the json return value looks fine and the filtered rows appear in my grid.
But the Loading... popup won't disappear and Firebug reports an error in ext-all-debug.js: TypeError: data is null (Line 134684). The code at that point is:
data = store.getData();
items = data.items; // error
I've checked my JS several times, but I can't find the problem.
Unfortunately I can't create a fiddle, since I use remote filtering. So here's the script:
Ext.onReady (function () {
Ext.define('FooModel', {
extend: 'Ext.data.Model',
fields: [
{ name: 'myId', type: 'int' },
{ name: 'myDate', type: 'date', dateFormat: 'Y-m-d H:i:s' },
{ name: 'myString', type: 'string' },
{ name: 'myFilename', type: 'string' },
{ name: 'myUser', type: 'string' }
]
});
Ext.define('FooStore', {
extend: 'Ext.data.Store',
model: 'FooModel',
autoLoad: true,
autoDestroy: true,
proxy: {
type: 'ajax',
url: 'test.php',
reader: {
type: 'json',
rootProperty: 'import_files',
messageProperty: 'error',
}
},
remoteFilter: true,
remoteSort: true,
sorters: [{
property: 'myId',
direction: 'ASC'
}],
pageSize: 5
});
var theFooStore = new FooStore();
theFooStore.load({
callback: function(records, operation, success) {
if(!success) {
Ext.Msg.alert('Error', operation.getError());
}
}
});
Ext.define('FooGrid', {
extend: 'Ext.grid.Panel',
xtype: 'grid-filtering',
requires: [ 'Ext.grid.filters.Filters' ],
width: 1000,
height: 700,
renderTo: 'content',
plugins: 'gridfilters',
emptyText: 'No Matching Records',
loadMask: true,
stateful: true,
store: theFooStore,
defaultListenerScope: true,
columns: [
{ dataIndex: 'myId', text: 'My Id', filter: 'number' },
{ xtype: 'datecolumn', dataIndex: 'myDate', text: 'My Date', renderer: Ext.util.Format.dateRenderer('d.m.Y'), filter: true },
{ dataIndex: 'myString', text: 'My String', filter: 'list' },
{ dataIndex: 'myFilename', text: 'My Filename',
renderer: function(value, meta, record) {
return Ext.String.format('{1}', record.data.myId, value);
},
filter: {
type: 'string',
itemDefaults: { emptyText: 'Search for...' }
}
},
{
dataIndex: 'myUser', text: 'My User',
filter: {
type: 'string',
itemDefaults: { emptyText: 'Search for...' }
}
},
],
dockedItems: [{
xtype: 'pagingtoolbar',
store: theFooStore,
dock: 'bottom',
displayInfo: true
}]
});
new FooGrid();
});
And here's a sample json return value:
{
"success" : true,
"total" : 19,
"import_files" : [{
"myId" : "1",
"myFilename" : "foo bar.xlsx",
"myDate" : "2015-05-19 13:23:21",
"myUser" : "ABC",
"myString" : "Lorem ipsum"
},
...
]
}
Has someone experienced the same issue? What could it cause?
Just my luck. Found the answer shortly after posting the question.
Deleting the filter: 'list' option at my My String column is the solution.
I have a Sencha Touch code base and I wanted to be able to use the "Enter" key to submit the initial log in to the application instead of having to click the button on a desktop. Here is my Login view:
Ext.define('App.view.Login', {
extend: 'Ext.form.Panel',
alias: 'widget.login',
requires:[
'Ext.form.FieldSet',
'Ext.field.Email',
'Ext.field.Password'
],
config: {
items: [
{
xtype: 'toolbar',
docked: 'top',
title: 'App'
},
{
xtype: 'fieldset',
margin: '.5em .5em 1.5em',
title: 'Login',
items: [
{
xtype: 'emailfield',
name: 'email',
placeHolder: 'email#example.com',
required: true
},
{
xtype: 'passwordfield',
name: 'password',
placeHolder: 'password',
required: true,
}
]
},
{
xtype: 'container',
layout: {
type: 'vbox'
},
margin: '10px',
items:[
{
xtype: 'button',
margin: '10px',
itemId: 'login',
text: 'Login'
}
]
}
]
}
});
And here is my Login controller:
Ext.define("App.controller.Login", {
extend: "Ext.app.Controller",
config: {
views: ["Login", "user.Home"],
stores: ["LoginInstance"],
refs: {
password: 'passwordfield[name="password"]',
login: {
autoCreate: true,
selector: "login",
xtype: "login"
}
},
control: {
password: {
keyup: function(field, e) {
if(e.event.keyCode === 13) {
console.log('Do login');
this.onLoginTap();
}
}
},
"login #login": {
tap: "onLoginTap"
},
// ...
}
},
onLoginTap: function() { ... } // do the login
However, this seems to not do anything (that is, not even the console.log appears in the console!). Does anyone have have suggestion as to what I could be doing wrong?
It looks like there's more than one issue in your code.
control doesn't target your password field. The key password references an component with xtype password. The correct way to reference it is either passwordfield if you never have more than one of them or 'passwordfield[name="password"]'.
the purpose of refs is to create a method of the controller like this.getPassword() to get the password field. Also the way you define it is invalid. It must be like refs: [{ref: 'password', selector: 'passwordfield[name="password"]'
you must not nest configurations inside a config property. extend: "Ext.app.Controller", config: { views: should be extend: "Ext.app.Controller", views:
I don't think this is exhaustive. There must be more issues.
Please read the documentation and don't try to code by trial and error. It is not a good programming practice.
My question s in relation to the possible answer in this post Sencha Touch 2 - How to get form values?
Im having the same issue trying to retrieve the values from a form in a View using a Controller.
My current error is Uncaught TypeError: Object # has no method 'getValues'
View:
Ext.define("App.view.Login", {
extend: 'Ext.form.Panel',
requires: [
'Ext.field.Password'
],
id: 'loginview',
config: {
items: [{
xtype: 'titlebar',
title: 'Login',
docked: 'top'
},
{
xtype: 'fieldset',
id: 'loginForm',
defaults: {
required: true
},
items: [{
items: [{
xtype: 'textfield',
name: 'username',
label: 'Username:'
},
{
xtype: 'passwordfield',
name: 'password',
label: 'Password:'
}]
}]
},
{
xtype: 'toolbar',
layout: {
pack: 'center'
}, // layout
ui: 'plain',
items: [{
xtype: 'button',
text: 'Register',
id: 'register',
ui: 'action',
}, {
xtype: 'button',
text: 'Login',
id: 'login',
ui: 'confirm',
}] // items (toolbar)
}]
}
});
Controller:
Ext.define('App.controller.Login', {
extend: 'Ext.app.Controller',
requires: [
'App.view.Login',
'Ext.MessageBox'
],
config: {
refs: {
loginForm: '#loginForm',
register: '#register',
login: '#login'
},
control: {
register: {
tap: 'loadRegisterView'
},
login: {
tap: 'loginUser'
}
},
history: null
},
loadRegisterView: function(btn, evt) {
/*var firststep = Ext.create('App.view.Register');
Ext.Viewport.setActiveItem(firststep);*/
},
loginUser: function(btn, evt) {
var values = loginForm.getValues();
console.log(values);
}
});
Thanks
Edit:
So the below code works but its not how i see everyone doing it.
var form = Ext.getCmp('loginview');
console.log(form.getValues());
Everyone else does this.getLoginView().getValues(); . I dont understand "this" is in the wrong scope and where would getLoginView even be declared? No one ever includes this information in their snippets. Here is another example Sencha Touch 2 - How to get form values?
Add xtype in view below the "id":
xtype: 'loginform',
and then replace the reference of loginForm with this:
loginForm: 'loginform',
Your code will work. The mistake you were doing is you were trying to access the method of 'formpanel' in 'fieldset'.
I'm new to Sencha ExtJS. I've just started creating a MVC application. Currently I'm trying to create a login screen for that application, but I can't get reference to my login form from login controller. Here is my code:
app.js
Ext.application({
name: 'Fleximanager',
requires: [
],
controllers: [
'Login'
],
autoCreateViewport: true,
init: function() {
}
});
Viewport.js
Ext.define('Fleximanager.view.Viewport', {
extend: 'Ext.container.Viewport',
requires:[
'Fleximanager.view.login.Flexilogin'
],
layout: 'fit',
items: [{
xtype:'flexilogin'
}]
});
Flexilogin.js
Ext.define('Fleximanager.view.login.Flexilogin', {
extend: 'Ext.panel.Panel',
xtype: 'flexilogin',
layout: {
type: 'vbox',
align: 'center',
pack: 'center'
},
id: 'flexilogin',
style: {background: '#8fc33a'},
items: [{
xtype:'panel',
title: 'Login',
frame: true,
width: 350,
height: 200,
layout: 'fit',
items: {
layout: 'anchor',
id: 'flexiloginform',
bodyPadding: 15,
defaultType: 'textfield',
items: [{
fieldLabel: 'Username',
name: 'username',
allowBlank: false
},{
fieldLabel: 'Password',
name: 'password',
inputType: 'password',
allowBlank: false
}],
buttons: [{
text: 'Register',
id: 'registerbtn',
action: 'register'
},{
text: 'Login',
id: 'loginbtn',
formBind: true,
}]
}
}]
});
and the controller's Login.js
Ext.define('Fleximanager.controller.Login', {
extend: 'Ext.app.Controller',
requires: [
'Fleximanager.view.login.Flexilogin',
],
refs:[{
ref: 'loginbtn',
selector: '#loginbtn'
}],
init: function(){
this.control({
'loginbtn': {
'click': function(){
console.log('click');
}
}
})
}
});
The code is supposed to log 'click' to console after you click the login button, but it does nothing. Can anyone help me?
Thanks for any answer.
The problem lies in how you are referencing the button.
refs:[{
ref: 'loginbtn',
selector: '#loginbtn'
}],
Is creating a reference getter method this.getLoginbtn to use in the controller, but it cannot be used in this.control
The string key in this.control is a identifier like defined in Ext.ComponentQuery.query. It searches for xtype/alias and itemId.
this.control({
'flexilogin #loginbtn': {
^ xtype ^ itemId
Note that you should use itemId instead of id because id must be unique on the page at any moment, itemId should be unique inside a component; change like this:
{
text: 'Login',
itemId: 'loginbtn',
^ replace id by itemId
formBind: true,
name: 'login'
}
Just give a name to your button like this,
{
text: 'Login',
id: 'loginbtn',
formBind: true,
name: 'login'
}
and now in controller, put this code:
this.control({
'button[name="login"]': {
click: function(){
console.log('click');
}
}
})
This will serve your purpose.