In my application, I have a log in window with two textfields (email and password) and submit button that submits those values to the server:
doLogin: function() {
var me = this,
form = me.lookupReference('form');
me.getView().mask('Authenticating... Please wait...');
form.submit({
clientValidation: true,
url: 'login.php',
scope: me,
success: 'onLoginSuccess',
failure: 'onLoginFailure'
});
},
I would like have an option ‘remember me on this device’ in login window, so the user doesn’t need to input credentials every time. My idea was to use cookies to store values for email and password.
So, I added a checkbox in login form, and upon successful log in, if checkbox is checked, I save email in cookie:
Ext.util.Cookies.set('MyApplication', user_email);
And the same I do for the password. Those cookies can be cleared on logout. At the very beginning of the application I can read those cookies
Ext.util.Cookies.get('MyApplication');
That could be done at the very beginning or for example on ‘beforerenderer’ event of login window.
But now comes the part when I should skip appearance of login window if the user selected that option. Actually, I don’t want to skip that window at all – I would just like to hide it and to maintain its actions.
So, is it possible at some place to add something like
if (Ext.util.Cookies.get('MyApplication')){
// 1. hide the login window so it won't appear at all
// 2. Set value of email and password textfields to stored values
// 3. Submit such hidden form to the server
}
You can set hidden in beforerender event and submit the form, in this case user will not see it (it will be rendered in hidden mode):
Ext.application({
name: 'Fiddle',
launch: function () {
Ext.create('Ext.form.Panel', {
title: 'Simple Form',
bodyPadding: 5,
width: 350,
// The form will submit an AJAX request to this URL when submitted
url: 'save-form.php',
// Fields will be arranged vertically, stretched to full width
layout: 'anchor',
defaults: {
anchor: '100%'
},
// The fields
defaultType: 'textfield',
items: [{
fieldLabel: 'Email',
name: 'email',
value: Ext.util.Cookies.get('email'),
allowBlank: false
}, {
fieldLabel: 'password',
name: 'password',
allowBlank: false,
inputType: 'password',
value: Ext.util.Cookies.get('password')
}],
// Reset and Submit buttons
buttons: [{
text: 'Reset',
handler: function () {
this.up('form').getForm().reset();
}
}, {
text: 'Submit',
formBind: true, //only enabled once the form is valid
disabled: true,
handler: function () {
var form = this.up('form').getForm();
if (form.isValid()) {
form.submit({
success: function (form, action) {
Ext.Msg.alert('Success', action.result.msg);
},
failure: function (form, action) {
Ext.Msg.alert('Failed', action.result.msg);
}
});
}
}
}],
listeners: {
beforerender: function(loginWindow) {
if(Ext.util.Cookies.get('email') && Ext.util.Cookies.get('password')) {
console.log('Hidden');
loginWindow.setHidden(true);
loginWindow.getForm().submit();
}
}
},
renderTo: Ext.getBody()
});
}
});
Related
When I load a store, due to the API structure, I get a json object inside my model:
Ext.define('TestApp.model.SecretKeyModel', {
extend: 'Ext.data.Model',
config:{
identifier: {
type: 'uuid'
},
fields: [
{ name:'theRecord', type:'json' }
]
},
extractToken: function() {
var record = this;
var token = record.initSession.token;
console.log('token: ' + token);
}
});
I need to extract the token from that json object.
For that, i think I should write a function right there, inside the model.
How can I call it, when the store loads, to manipulate the data and extract the token?
I faced a similar situation 1 hour ago, i needed to edit data during loading or immidiatly after. I ended with this solution:
Ext.define('TestApp.store.MyStore', {
extend: 'Ext.data.Store',
requires: ['TestApp.model.SecretKeyModel'],
config :{
model: 'TestApp.model.SecretKeyModel',
proxy: {
type: 'ajax',
url: TestApp.utils.GlobalVariables.getServerUrl(),
reader: {
type: 'json',
rootProperty: ''
}
},
listeners: {
refresh: function(store, data, eOpts) {
store.each(function (item, index, length) {
item.extractToken(); // call this on every record loaded in the store
});
}
}
}
});
I am developing a Sencha Touch 2 app with user authentication.
I use a token for authentication.
The logic.
Check is a token exists in local storage:
var tokenStore = Ext.getStore('TokenStore'),
token = tokenStore.getAt(0).get('token');
If there is a token, check if it's valid.
I am doing a read from a model which is connected to my API which, returns success or fail - depending on the token - if it's valid or not.
TestApp.model.CheckAuthModel.load(1, {
scope: this,
success: function(record) {
// Here, I know the token is valid
},
failure: function() {
console.log('failure');
},
callback: function(record) {
console.log('callback');
console.log();
}
});
And here is the router, which handles the logic for the views:
Ext.define("TestApp.controller.Router", {
extend: "Ext.app.Controller",
config: {
refs: {
HomeView: 'HomeView',
LoginView: 'LoginView',
ProductsView: 'ProductsView',
ProductsViewTwo: 'ProductsViewTwo'
},
routes: {
'': 'home',
'home' : 'home',
'login' : 'login',
'products' : 'products',
'testingtwo' : 'testingtwo'
}
},
home: function () {
console.log('TestApp.controller.Router home function');
var initialItem = Ext.Viewport.getActiveItem(),
comp = this.getHomeView();
if (comp === undefined) comp = Ext.create('TestApp.view.HomeView');
Ext.Viewport.animateActiveItem(comp, {
type: 'slide',
listeners: {
animationend: function() {
initialItem.destroy();
}
}
});
},
login: function () {
var initialItem = Ext.Viewport.getActiveItem(),
comp = this.getLoginView();
if (comp === undefined) comp = Ext.create('TestApp.view.LoginView');
Ext.Viewport.animateActiveItem(comp, {
type: 'slide',
listeners: {
animationend: function() {
initialItem.destroy();
}
}
});
},
products: function () {
var initialItem = Ext.Viewport.getActiveItem(),
comp = this.getProductsView();
if (comp === undefined) comp = Ext.create('TestApp.view.ProductsView');
Ext.Viewport.animateActiveItem(comp, {
type: 'slide',
listeners: {
animationend: function(){
initialItem.destroy();
}
}
});
},
testingtwo: function () {
var initialItem = Ext.Viewport.getActiveItem(),
comp = this.getProductsViewTwo();
if (comp === undefined) comp = Ext.create('TestApp.view.ProductsViewTwo');
Ext.Viewport.animateActiveItem(comp, {
type: 'slide',
listeners: {
animationend: function(){
initialItem.destroy();
}
}
});
},
launch: function() {
console.log('TestApp.controller.Router launch!');
}
});
Now, how can I link the router with the check auth model callback?
I want to know the auth state when the app reaches the router.
In other MVC frameworks, I could do a before filter, on the router, check for auth and handle the routes accordingly.
Can i do this in Sencha Touch 2?
Any ideas?
Hi I think this section in the documentation is exactly what you need:
before : Object
Provides a mapping of Controller functions to filter functions that are run before them when dispatched to from a route. These are usually used to run pre-processing functions like authentication before a certain function is executed. They are only called when dispatching from a route. Example usage:
Ext.define('MyApp.controller.Products', {
config: {
before: {
editProduct: 'authenticate'
},
routes: {
'product/edit/:id': 'editProduct'
}
},
//this is not directly because our before filter is called first
editProduct: function() {
//... performs the product editing logic
},
//this is run before editProduct
authenticate: function(action) {
MyApp.authenticate({
success: function() {
action.resume();
},
failure: function() {
Ext.Msg.alert('Not Logged In', "You can't do that, you're not logged in");
}
});
}
});
http://docs.sencha.com/touch/2.3.1/#!/api/Ext.app.Controller-cfg-before
Of course, it's still up to you to decide whether you should check every time or should cache the auth result for sometime.
Updated to answer comment below
Honestly, i am not sure how they was going to declare that static method Authenticate in Sencha (you would be able to do it normally through Javascript i think, i.e.: prototype).
But there are other better options to solve just that Authenticate function:
Just create a singleton class that handle utility stuffs.
http://docs.sencha.com/touch/2.3.1/#!/api/Ext.Class-cfg-singleton
If you really want to use MyApp, you can declare within the Ext.app.Application (in app.js). Then call it from the global instance MyApp.app.some_function(). I wouldn't exactly recommend this method because you change app.js, that might bring problem if you upgrade sencha touch.
You could implemented auth check in application's launch function or in your auth controller's init function and based on the response redirect the to appropriate url. Something like this:
TestApp.model.CheckAuthModel.load(1, {
scope: this,
success: function(record) {
this.redirectTo("home/");
},
failure: function() {
this.redirectTo("login/");
console.log('failure');
},
callback: function(record) {
console.log('callback');
console.log();
}
});
Common form with Ext.direct submit n load, load is working properly, but submit is return error, coz in post data in undefined
var _form = Ext.create('Ext.form.Panel', {
api: {
submit: submit, //actions I took from code that going above, and never mind what I ll write here. Its not a problem
load: load
},
baseParams: {
st_id: st_id,
id: id
},
paramsAsHash: true,
defaultType: 'textfield',
buttons: [{
text: 'Cancel',
handler: function() {
this.up('form').getForm().reset();
}
}, {
text: 'Save',
handler: function() {
var values = this.up('form').getForm().getValues();
this.up('form').getForm().submit({
success: function() {
grid.getStore().load();
}
});
this.up('form').getForm().reset();
}
}]
});
in to headers wrote that content type is "application/json;" but in other cases its "application/x-www-form-urlencoded", last it make sense, right? and it work, but in other forms.
all of this is under Kohana, so when I look clearly what is going on in controllers, in Extdirect Router I see what for this form there is no info about submit method.
it was kind of stupid mistake: I forgot #formHandler in a definition
I'm trying to upload a file using Ext JS forms and in case of success or failure, show appropriate messages. But I'm not able to get the desired result. I'm not able to make success or failure callbacks work in form.submit action.
What I've done till now is:
Creating a form with this script:
new Ext.FormPanel({
fileUpload: true,
frame: true,
url: '/profiler/certificate/update',
success: function() {
console.log(arguments);
},
failure: function() {
console.log(arguments);
}
}).getForm().submit()
/*
The response Content-Type is text/html (with charcode=utf8);
The response JSON is: { "success": true }
*/
Setting the response Content-Type to text/html based on this answer.
Sending an appropriate JSON result back, based on Ext JS docs. The response captured via Fiddler is:
{"success":false}
or
{"success":true}
I even set the response Content-Type to application/json. But still no success.
I've read links like this and this, but none of them helped. Please note that I also tried another script which creates a form, with an upload field in it, and a save button, and I submitted the form in the handler of the save button. But still no callback is fired.
Here's a working example - Javascript code:
Ext.onReady(function () {
Ext.define('ImagePanel', {
extend: 'Ext.form.Panel',
fileUpload: true,
title: 'Upload Panel',
width: 300,
height: 100,
onUpload: function () {
this.getForm().submit({
url: 'upload.php',
scope: this,
success: function (formPanel, action) {
var data = Ext.decode(action.response.responseText);
alert("Success: " + data.msg);
},
failure: function (formPanel, action) {
var data = Ext.decode(action.response.responseText);
alert("Failure: " + data.msg);
}
});
},
initComponent: function () {
var config = {
items: [
{
xtype: 'fileuploadfield',
buttonText: 'Upload',
name: 'uploadedFile',
listeners: {
'change': {
scope: this,
fn: function (field, e) {
this.onUpload();
}
}
}
}
]
};
Ext.apply(this, Ext.apply(this.initialConfig, config));
this.callParent(arguments);
}
});
var panel = Ext.create('ImagePanel', {
renderTo: Ext.getBody()
});
});
And PHP code:
<?php
if (isset($_FILES)) {
$temp_file_name = $_FILES['uploadedFile']['tmp_name'];
$original_file_name = $_FILES['uploadedFile']['name'];
echo '{"success": true, "msg": "'.$original_file_name.'"}';
} else {
echo '{"success": false, "msg": "No Files"}';
}
I have been struggling with this for quite some time now as well. Here's my code:
Ext.getCmp('media-upload-form').getForm().doAction('submit', {
url: './services/recordmedia/upload',
method: 'post',
waitMsg: 'Please wait...',
params: {
entityId: this.entityId,
},
failure: function(form, action){
alert(_('Error uploading file'));
this.fireEvent('file-upload');
this.close();
},
success: function(form, action){
this.fireEvent('file-upload');
this.close();
},
scope: this
})
The response was always wrapped in <pre> tags by the browser, what caused the Extj lib not to call the callbacks. To fix this:
make sure your server returns the correct json: {"success":true}
make sure that the content-type is set to text/html
Actually, this is well covered by docs for Ext.form.Panel and Ext.form.Basic. The problem with your code not working is that there are no config options "success", "failure" for the form panel. You should put them in the config object passed to the submit action. So your code should look like:
new Ext.FormPanel({
fileUpload: true,
frame: true
}).getForm().submit({
url: '/profiler/certificate/update',
success: function() {
console.log(arguments);
},
failure: function() {
console.log(arguments);
}
});
Note the difference: In Ext 4, there is a form component (Ext.form.Panel) which is basically a view component concerned with how you form looks, and then there is the underlying form class (e.g. Ext.form.Basic) concerned with the functionality. Form submissions are handled by Ext.form.Basic (or whatever returned by your form.getForm()).
I have a list of news in a Ext.List inside a panel
prj.views.NewsList = Ext.extend(Ext.Panel, {
layout: 'card',
initComponent: function() {
this.list = new Ext.List({
itemTpl: '......',
loadingText: false,
store: new Ext.data.Store({
model: 'News',
autoLoad: true,
proxy: {
type: 'ajax',
url: '.....',
reader: {
type: 'json',
//root: ''
}
},
listeners: {
load: { fn: this.initializeData, scope: this }
}
})
});
this.list.on('render', function(){
this.list.store.load();
this.list.el.mask('<span class="top"></span><span class="right"></span><span class="bottom"></span><span class="left"></span>', 'x-spinner', false);
}, this);
this.listpanel = new Ext.Panel({
items: this.list,
layout: 'fit',
listeners: {
activate: { fn: function(){
this.list.getSelectionModel().deselectAll();
Ext.repaint();
}, scope: this }
}
})
this.items = this.listpanel;
prj.views.NewsList.superclass.initComponent.call(this);
},
});
Ext.reg('newsList', prj.views.NewsList);
In a toolbar setup in a dockedItem, I have a icon to refresh the list.
items: [
{
iconCls: 'refresh',
handler: function() {
prj.view.NewsList.list.store.read()
}
},
]
but prj.view.NewsList return undefined! How can I get the list to do a refresh of the store?
Call this line on your refresh button
Ext.StoreMgr.get('newsStore').load()
The list is automaticaly refresh when you call the load() method on the store. The store is linked to the list.
Example:
items: [
{
iconCls: 'refresh',
handler: function(event, btn) {
Ext.StoreMgr.get('newsStore').load();
}
},
]
Even I faced a similar problem.
I am posting my answer hope this helps someone.
I have a search bar in to search data. (my search is taking place at server and the results are sent back to me in response to my GET request.
Basically I just had to change the URL for my store
WHAT ALL I TRIED:
myList.refresh(),
myStore.load();
clearing the store and then loading it
removing the list and adding it again and forcing it to re render (using doLayout())
Nothing worked...
just adding SINGLE line fixed my problem
function handleSearch(strSearchText)
{
//myStore.loadData([],false); /tried to clear the store and reloading it
if(strSearchText !='')
{
searchString = '?search='+strSearchText;
searchURL = searchURLBasic+ searchString;
}else{
searchURL = searchURLBasic;
}
console.log('search URL: ' + searchURL);
myStore.proxy.url =searchURL; // this was one magical line of code that saved my life
myStore.load();
}
THanks SO for support.
I do this when changing the store and it works like a champ
var yourbutton = new Ext.Panel({
listeners: {
afterrender: function(c){
c.el.on('click', function(){
YourList.update();
YourList.bindStore(newStore);
});
}
}
});