Extjs how submit form without ajax? - javascript

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...

Related

Add QR code using external javascript file within Sencha framework

We are trying to add functionality to an old system. Our clients use scanners, so it would be ideal if we could add a QR code on screen for them to scan. I found a small open source javascript library that displays QR codes. I wanted to use that, but I am pulling the URL from the database, putting it into a Store, and then populating a link on screen. So, I have the following:
this.searchForm = {
frame: true,
xtype: 'form',
layout: 'form',
labelWidth: 150,
items: [{
xtype: 'component',
fieldLabel: 'Wireless App',
tpl: '<div id="qrcode" style="width:100px; height:100px;"></div>{Url}',
data: { Url: '' },
ref: '../../WirelessAppLabel'
}, {
xtype: 'label',
ref:'../../StatusLabel'
}]
};
lookupRF: function(search) {
this.createRFLookup();
this.lookupRFWindow.show();
this.WirelessAppStore = WirelessAppUrl.getInstance().createStore();
PM.Retriever.retrieve([this.WirelessAppStore], {
callback: function (response, success) {
if (success) {
this.WMSAppUrl = this.WirelessAppStore.data.items[0].data.Url;
this.lookupRFWindow.WirelessAppLabel.update({ Url: this.WMSAppUrl });
new QRCode(document.getElementById("qrcode"), this.WMSAppUrl);
}
},
scope: this
});
}
where PM is a namespace we created internally. (These two functions are not in the same file, but one references the other). But, I keep getting errors saying QRCode is not defined. I tried loading it using Ext.Loader.load() and also just adding a reference to the script in index.html, but neither option worked. Any suggestions?
Here is the link to the QR Code javascript we are attempting to utilize: https://davidshimjs.github.io/qrcodejs/
I found a much easier approach. Rather than try to do everything in Javascript, it is already hitting the server to pull from the database, so I added a QR Code generator that created a Bitmap server side, which converts it into a Base64String. So, now my code looks like this:
this.searchForm = {
frame: true,
xtype: 'form',
layout: 'form',
labelWidth: 150,
items: [{
xtype: 'component',
fieldLabel: 'Wireless App',
tpl: '{Url}<br/><img src="data:image/jpeg;base64, {Image}" style="width:100px;height:100px;" />',
data: {
Url: '',
Image: ''
},
ref: '../../WirelessAppLabel'
}, {
xtype: 'label',
ref:'../../StatusLabel'
}]
};
lookupRF: function(search) {
this.createRFLookup();
this.lookupRFWindow.show();
this.WirelessAppStore = WirelessAppUrl.getInstance().createStore();
PM.Retriever.retrieve([this.WirelessAppStore], {
callback: function (response, success) {
if (success) {
this.WMSAppUrl = this.WirelessAppStore.data.items[0].data.Url;
this.WMSAppImage = this.WirelessAppStore.data.items[0].data.QRCode;
this.lookupRFWindow.WirelessAppLabel.update({
Url: this.WMSAppUrl,
Image: this.WMSAppImage
});
}
},
scope: this
});
And then to actually create the QRCode, I used this open source package: https://github.com/codebude/QRCoder
Not exactly the solution that was asked for, but it works really well.

How do I set data in an unrelated ViewModel

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 :/

Added an enter event to EXT JS Application search text box to fire search

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

ExtJS 4 TreePanel autoload

I have an Ext.tree.Panel which is has a TreeStore. This tree is in a tab. The problem is that when my application loads all of the trees used in the application load their data, even though the store is on autoLoad: false.
How could I prevent autoloading on the tree?
Ext.define('...', {
extend: 'Ext.container.Container',
alias: 'widget.listcontainer',
layout: {
type: 'vbox',
align: 'stretch'
},
items: [{
xtype: 'container',
html: "...",
border: 0
}, {
xtype: '...',
flex: 1,
bodyPadding: 5,
margin: '9 0 0 0'
}]
});
Ext.define('...', {
extend: 'Ext.data.TreeStore',
model: '...',
proxy: {
type: 'ajax',
reader: {
type: 'json',
root: 'data'
},
api: {
read: 'some url'
}
}
});
Ext.define('...', {
extend: 'Ext.tree.Panel',
alias: 'widget....',
id: '...',
title: '...',
height: 400,
collapsible: true,
useArrows: true,
rootVisible: false,
multiSelect: true,
singleExpand: true,
autoScroll: true,
store: '...',
columns: [...]
});
P.S. I've found out if I change rootVisible to true on the tree this problem doesn't happen, but then it shows to root node(which I don't want).
I hit the same problem, and to avoid an implicit request, I specified a root inline in the TreeStore's configuration, like:
Ext.create('Ext.data.TreeStore', {
model: '...',
proxy: {
type: 'ajax',
reader: {
type: 'json',
root: 'data'
},
api: {
read : 'some url'
}
folderSort: true,
rootVisible: false,
root: {expanded: true, text: "", "data": []} // <- Inline root
});
After an explicit .load the inline root is overwritten.
If root is invisible then AJAX tree will automatically load first level of hierarchy (as you already proved by yourself).
I think the best way is to make root visible or create tree after some actions. I wrote code that prevent AJAX request that loads data:
var preventTreeLoad = true;
store.on('beforeexpand', function(node) {
if (node == this.getRootNode() && preventTreeLoad) {
Ext.Ajax.abort(this.proxy.activeRequest);
delete this.proxy.activeRequest;
}
}, store);
var b = Ext.create('Ext.Button', {
text: 'Click me',
renderTo: 'btn',
});
b.on('click', function() {
preventTreeLoad = false;
this.load();
}, store);
But I'm not recommended to use this approach. For example, if javascript wasn't so fast - Ajax request may be send (response will not be read but server will execute operation).
You can put a dummy proxy in place when defining the tree, then set the real proxy when you want to begin using the tree/store. For example:
var store = Ext.define('Ext.data.TreeStore', {
...
// dummy proxy to avoid autoLoad on tree store construction
proxy: {
type: 'ajax',
url: ''
},
...
);
Then, when you want to use it for the first time,
store.setProxy({
type: 'ajax',
url: 'http://some/real/url',
...
});
store.load();
You can solve it with a small override:
Ext.override(Ext.tree.View,
{
setRootNode: function(node)
{
var me = this;
me.store.setNode(node);
me.node = node;
if (!me.rootVisible && me.store.autoLoad)
{
node.expand();
}
}
});
afterlayout you need a load()
Adding to what XenoN said (though many years later when I hit the same issue)
If the expanded property is set to true in the store definition, it will auto load even if autoLoad is set to false. this is unique to a TreeStore.
However, if we do want the store to load and expand we need to
Set expanded = true sometimes in code after creation (when we want) this also fires the loading of the previously created store.
setting store.setRoot({expanded:true}); within the consumer of the store which is Ext.tree.Panel.
This will load the store when you want it to load it.
seems like after that, store.load() is redundant since the expanded = true makes the store's proxy to load up and go to the server. weird, I know.
Simplest way is setting Store's root property
Ext.create('Ext.data.TreeStore', {
....
autoLoad:false,
root: {
expanded: false
}
});
Try with children and autoLoad : false :
root: {
children : []
}

extJS login window + rails

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.

Categories