I have a sign in process that I've roughed into a fiddle (the part I'm stuck on starts at line 110).
Here's a copy of the code:
Ext.define('MyApp.MyPanel',{
extend: 'Ext.panel.Panel',
title: 'My App',
controller: 'mypanelcontroller',
viewModel: {
data:{
email: 'Not signed in'
}
},
width: 500,
height: 200,
renderTo: Ext.getBody(),
bind:{
html: "Logged in as: <b>{email}</b>"
},
buttons:[
{
text: 'Sign in',
handler: 'showSignInWindow'
}
]
});
Ext.define('MyApp.MyPanelController',{
extend: 'Ext.app.ViewController',
alias: 'controller.mypanelcontroller',
showSignInWindow: function (b,e,eOpts){
Ext.widget('signinwindow').show();
}
});
Ext.define('MyApp.SignInWindow',{
extend: 'Ext.window.Window',
title: 'Sign in',
controller: 'signincontroller',
xtype: 'signinwindow',
width: 400,
title: 'Sign In',
modal: true,
layout: 'fit',
items:[
{
xtype: 'form',
reference: 'signinfields',
layout: 'anchor',
bodyPadding: 5,
defaults: {
anchor: '100%',
xtype: 'textfield'
},
items:[
{
fieldLabel: 'Email',
name: 'email',
allowBlank: false
},
{
fieldLabel: 'Password',
name: 'password',
allowBlank: false,
inputType: 'password'
}
],
buttons:[
{
text: 'forgot password',
width: 120,
//handler: 'onForgotPassword'
},
'->',
{
text: 'sign in',
width: 120,
handler: 'onSignIn'
}
]
}
]
});
Ext.define('MyApp.SignInController',{
extend: 'Ext.app.ViewController',
alias: 'controller.signincontroller',
onSignIn: function (button, event, eOpts){
var data = button.up('form').getValues();
button.up('window').mask('Signing in...');
Ext.Ajax.request({
// sorry, I don't know how to fake an API response yet :/
url: '/authenticate/login',
jsonData: data,
scope: this,
success: function (response){
var result = Ext.decode(response.responseText);
if(result.loggedIn == true){
/*
This is where I need help.
From the sign in window, I would like to update the viewmodel in `MyApp.MyPanel` with the
email returned in the response. If the window was a child of MyPanel, I would be able to update
via the ViewModel inheritance, but I can't here because the window isn't part of the `items` config.
*/
this.getViewModel().set('email', result.data[0].email);
Ext.toast({
title: 'Sign in successful',
html: "You've been signed in.",
align: 't',
closable: true,
width: 300
});
button.up('window').destroy();
} else {
Ext.toast({
title: 'Sign in failed',
html: "You sign in failed: " + result.message,
closable: true,
width: 300,
align: 't'
});
button.up('window').unmask();
}
},
failure: function (){
// debugger;
}
})
},
onForgotPassword: function (){
Ext.Ajax.request({
url: '/authenticate/test',
success: function (response){
},
failure: function (){
}
})
// Ext.Msg.alert('trigger forgot password logic', "This is where you need to trigger the API to send the forgot email form. <br>Say something here about how you'll get an email");
}
});
Ext.application({
name : 'Fiddle',
launch : function() {
Ext.create('MyApp.MyPanel');
}
});
What I'm trying to do is:
Show a panel with a sign in button
Clicking on the button shows a sign in window
Submitting the sign in form attempts an authentication against the server
On a successful authentication, the email for the user is set in the initial panel's ViewModel
The last bullet is what I'm having a problem with.
If the sign in window was a child of the panel then I could set it through the ViewModel inheritance, but since I'm using a widget show I can't set back through the panel's items config.
Is there a way of doing this correctly?
Nevermind, I figured it out. The answer was in my question all along:
If the sign in window was a child of the panel then I could set it through the ViewModel inheritance, but since I'm using a widget show I can't set back through the panel's items config.
Just make the window a child of the panel:
Ext.define('MyApp.MyPanelController',{
extend: 'Ext.app.ViewController',
alias: 'controller.mypanelcontroller',
showSignInWindow: function (b,e,eOpts){
// Instead of creating the widget and showing it, create it and add it to the panel.
// The window is going to float anyway, so being a child of the panel is no big deal
var signinwindow = Ext.widget('signinwindow');
this.getView().add(signinwindow).show();
}
});
Doing it this way means the window inherits the viewmodel of the panel and you can set the viewmodel data like so:
Ext.define('Registration.view.signin.SignInController', {
extend: 'Ext.app.ViewController',
alias: 'controller.signin-signin',
onSignIn: function (button, event, eOpts){
var data = button.up('form').getValues();
button.up('window').mask('Signing in...');
Ext.Ajax.request({
url: '/authenticate/login',
jsonData: data,
scope: this,
success: function (response){
debugger;
var result = Ext.decode(response.responseText);
if(result.loggedIn == true){
// Now that the window has inherited the panel's viewmodel
// you can set it's data from the windows controller
this.getViewModel().set('username', result.data[0].eMail);
...
emoji-for-exasperated :/
Related
So i have this function onDisplayError which is called each time if request fails. This means if user press save button and 3 request are failing i currently getting 3 popup messages. My goal is that this function checks if my popup window is already opened. If it is then i will append errors in my already opened window otherwise it should open this error popup
onDisplayError: function (response, message) {
var errorPanel = Ext.create('myApp.view.popup.error.Panel',{
shortMessage: message,
trace: response
});
if(errorPanel.rendered == true){
console.log('Do some other stuff');
}else{
errorPanel.show();
}
},
This is Panel.js
Ext.define('myApp.view.popup.error.Panel', {
extend: 'Ext.panel.Panel',
requires: [
'myApp.view.popup.error.PanelController'
],
controller: 'myApp_view_popup_error_PanelController',
title: 'Fail',
glyph: 'xf071#FontAwesome',
floating: true,
draggable: true,
modal: true,
closable: true,
buttonAlign: 'center',
layout: 'border',
shortMessage: false,
width: 800,
height: 200,
initComponent: function() {
this.items = [
this.getMessagePanel(),
this.getDetailsPanel()
];
this.callParent(arguments);
},
getMessagePanel: function() {
if(!this.messagePanel) {
var message = this.shortMessage;
this.messagePanel = Ext.create('Ext.panel.Panel', {
bodyPadding: 5,
height: 200,
region: 'center',
border: false,
html: message
});
}
return this.messagePanel;
},
getDetailsPanel: function() {
if(!this.detailsPanel) {
this.detailsPanel = Ext.create('Ext.panel.Panel', {
title: 'Details',
hidden: true,
region: 'south',
scrollable: true,
bodyPadding: 5,
height: 400,
html: '<pre>' + JSON.stringify(this.trace, null, 4) + '</pre>'
});
}
return this.detailsPanel;
}
The problem is that i'm still getting multiple popups displayed. I think that the problem is that var errorPanel loses reference so it can't check if this popup (panel) is already opened. How to achieve desired effect? I'm working with extjs 6. If you need any additional information's please let me know and i will provide.
You could provide to your component definition a special xtype.
Ext.define('myApp.view.popup.error.Panel', {
extend: 'Ext.panel.Panel',
xtype:'myxtype'
and then you could have a very condensed onDisplayError function:
onDisplayError: function (response, message) {
var errorPanel = Ext.ComponentQuery.query('myxtype')[0] || Ext.widget('myxtype');
errorPanel.appendError(message, response)
errorPanel.show();
},
The panel's initComponent function should initialize an empty window, and appendError should contain your logic to append an error (which may be the first error as well as the second or the third) to the list of errors in the panel.
Using Ext.create will always create a new instance of that class.
You can use the reference config to create a unique reference to the panel.
Then, use this.lookupReference('referenceName') in the controller to check if the panel already exists, and show().
You also have to set closeAction: 'hide' in the panel, to avoid panel destruction on close.
Otherwise, you can save a reference to the panel in the controller
this.errorPanel = Ext.create('myApp.view.popup.error.Panel' ....
Then, if (this.errorPanel) this.errorPanel.show();
else this.errorPanel = Ext.create...
my application is web desktop using 4.2 extjs. i just want to add my window a controller so that i can create a MVC but i cant figure out how to add the controller.
Here's my code. The win variable is always undefined. how to fix it.?
please help
Ext.define('MyDesktop.Modules.Itemmanagement.Client.Itemmanagement', {
requires: ['Ext.tab.Panel',
'Ext.ux.CheckColumn'],
id: 'itemmanagement-win',
init: function () {
var me = this;
this.launcher = {
text: 'Itemmanagement Module ',
iconCls: 'icon-itemmanagement',
handler: this.createWindow,
scope: this
};
},
createWindow: function () {
var me = this;
var desktop = this.app.getDesktop();
var win = desktop.getWindow('itemmanagement-win');
if (!win) {
Ext.application({
name: 'USER',
appFolder: '/modules/',
controllers: [
"User"
],
launch: function () {
win = desktop.createWindow({
id: 'itemmanagement-win',
title: 'Item Management',
width: 600,
height: 505,
iconCls: 'icon-itemmanagement',
animCollapse: false,
constrainHeader: true,
layout: 'fit'
});
}
});
}
win.show();
return win;
}
});
Create the window in your current application and don't create a new application.
createWindow: function () {
var me = this;
var desktop = this.app.getDesktop();
var win = desktop.getWindow('itemmanagement-win');
if (!win) {
win = desktop.createWindow({
id: 'itemmanagement-win',
title: 'Item Management',
width: 600,
height: 505,
iconCls: 'icon-itemmanagement',
animCollapse: false,
constrainHeader: true,
layout: 'fit'
});
}
win.show();
return win;
}
Define a controller in your controller folder (e.g. app/controller/ItemmanagementWindow.js).
Add it to your controller section in your Application.
Call in the init function this.control() with component queries you are interested and listen to the events.
Ext.define('MyDesktop.controller.ItemmanagementWindow',{
extend: 'Ext.app.Controller',
init: function(){
this.control({
// selector of window we want to add listeners to
'#itemmanagement-win' : {
// events we listen to
afterrender: this.onAfterRender
}
});
},
// handler function of the afterrender event
onAfterRender: function(window, eOpts){
//do some stuff in the after render event ...
}
});
See Application, ComponenQueries and MVC architecture for more informations
Hi I have the code below my my enter event is never triggering, any help will be appreciated.
items: [{
xtype: 'textfield',
id: 'idhere',
name: 'namehere',
fieldLabel: 'lablehere:',
width: 500,
handler: {
key:13,
fn : function () {
if (e.getKey() == e.ENTER) {
alert("You pressed an enter button in text field.");
}
}
}
},{
xtype: 'button',
text: 'texttodisplay',
handler: function() {
//my function.
}
}]
I actually solved this by using:
listeners: {
specialkey: function (f,e) {
if (e.getKey() == e.ENTER) {
loadData();
}
}
}
I am not sure why Sencha never included Ext.ux.form.SearchField in the API docs but the component has been included in all versions of the framework I've used. It is set-up to fire a submit and a cancel event and includes the appropriate search and cancel buttons attached to the field.
You can find it in your framework files at: [extjs-root]\examples\ux\form\SearchField.js
I would recommend using that component instead of trying to create your own searchfield. I usually override the default search function to fit my own needs but there have been a few scenarios where I did not need to also.
If you add a requires statement at the top of your component JS you can create it like any other (non-UX) component:
E.g:
Requires statement:
Ext.define('MyApp.view.SomeComponent', {
extend: 'Ext.grid.Panel',
alias: 'widget.mycomponent',
requires: [
'Ext.ux.form.SearchField'
],
...
Creating a search field in the panel's bottom toolbar:
bbar: {
items: [{
text: 'A Button'
}, {
text: 'Another Button'
}, '-', {
xtype: 'searchfield', // <- can use this xtype with requires stmt
itemId: 'search',
width: 250,
emptyText: 'Enter first and last name to search...'
}]
},
...
If you have trouble with the requires statement you could also just create it like this:
var search = Ext.create('Ext.ux.form.SearchField', {
itemId: 'search',
width: 250,
emptyText: 'Enter first and last name to search...'
});
Just to supply how to add such a listener. There is a specialkey event that can be used for such a case
fieldinstance.on('specialkey', function(f, e){
if (e.getKey() == e.ENTER) {
// your action
}
});
Anyway I recommend to use the ux component that #Geronimo mentioned
Good day!
I am try submit extjs form without ajax and show result on the next page. This is my code:
Ext.define('test.from', {
extend: 'Ext.form.Panel',
alias: 'widget.test.form',
initComponent: function () {
var me = this;
Ext.apply(this, {
frame: true,
bodyPadding: 7,
border: 0,
items: [{
xtype: 'textfield',
fieldLabel: 'First Name',
name: 'contact_attr'
}, {
xtype: 'textfield',
fieldLabel: 'Last Name',
name: 'contact_attr'
}],
buttons: [{
text: 'Send',
handler: function () {
me.getForm().submit({
url: '/salary/public/auth/',
standardSubmit: true,
method: 'POST'
});
}
}]
});
But redirect to other page doesn't occur and I receive error: You're trying to decode an invalid JSON String. Can anybody help me? Thank you!
ok, so you have 2 error.
why not redirect(standarssubmit), and
why you got "error decode"
i guess you're using extjs4:
1 . From the docs api. it say that submit() method is Shortcut to do a submit action. and the parameter is The options to pass to the action (see doAction for details). so, putting standardSubmit to submit method isn't the correct way. there is no standardSubmit option. more info. myanswer, you have 2 alternative way.
first, use the init:
Ext.apply(this,{
standardSubmit:true, // not working...
frame: true,
bodyPadding: 7,
.......
Edits:
.......
me.getForm().standardSubmit=true; //just like OP comment
me.getForm().submit({
url: '/salary/public/auth/',
standardSubmit: true,
method: 'POST'
});
.......
second, use doAction:
...
me.getForm().doAction('standardsubmit',{
url: '/salary/public/auth/',
standardSubmit: true,
method: 'POST'
});
...
2 . the error decode, i don't know what is your salary/public/auth look like....
try my first solution, if error exists, it mean the error is somewhere else...
I have cotnrol_admin:
def login
if request.post?
if params[:full_name] == "mg" && params[:password] == "123"
data = { :success => 'true', :msg => "Welcome, #{params[:full_name]}"}
#redirect_to :action => :welcome
#render :action => :welcome
else
data = { :failure => 'true', :msg => "Username or Password wrong !"}
end
render :text => data.to_json, :layout => false
end
end
I have this login.js
var loginForm = new Ext.form.FormPanel({
baseCls: 'x-plain',
labelWidth: 75,
url:'/admin/login',
defaultType: 'textfield',
items: [{
fieldLabel: 'Login',
name: 'full_name',
anchor:'90%' // anchor width by percentage
},{
fieldLabel: 'Password',
name: 'password',
inputType: 'password',
anchor: '90%' // anchor width by percentage
}],
buttons: [{
text: 'Login',
handler: function() {
loginForm.getForm().submit(
{
method: 'POST',
waitMsg:'Submitting...',
reset : false,
success : function() {
loginWindow.close();
},
failure: function(form, action){Ext.Msg.alert('Error',action.result.text)}
});
}
}]
});
var loginWindow = new Ext.Window({
title: 'Login',
width: 300,
height:140,
closable:false,
minWidth: 300,
minHeight: 140,
layout: 'fit',
plain:true,
modal:true,
bodyStyle:'padding:5px;',
items: loginForm
});
Ext.onReady(function(){
loginWindow.show(this);
});
So my questions is: everythings work pefectly. But when i press refresh button this login form comes again, how i can avoid this? I think about session. right? but how to integrate session in extJS or rails?
Yup, you though correctly, you need to use session. If you are beginner read about session management. RoR related session details can be found here.
When you login for the first time, if the user provided the correct information.. you need to create a session and store some info into it(for validating the session). When the use hit the URL again, first you need to check if the session is valid or not. If valid, you can simply forward the user to the application home page. Otherwise, the login page is displayed again.