As the user has the option to log in to the application, the user can also log out from it. Inside the Header
class, we have already declared the logout
button. The only thing pending is to implement the listener inside MainController
.
As the MainController
class was created by Sencha Cmd, we are reusing it. The file already has some code in it. Let's remove any listener created by Sencha. MainController
will look like this:
Ext.define('Packt.view.main.MainController', {
extend: 'Ext.app.ViewController',
requires: [
'Ext.MessageBox'
],
alias: 'controller.main',
//we will insert code here
});
In the Header
class, we declared the logout
button, its reference, and its listener. So we need to implement the onLogout
function, as follows:
onLogout: function(button, e, options){ var me = this; //#1 Ext.Ajax.request({ url: 'php/security/logout.php', //#2 scope: me, //#3 success: 'onLogoutSuccess', //#4 failure: 'onLogoutFailure' //#5 }); },
The me
(#1
) variable makes a reference to this
, which is the MainController
class. We will make an Ajax call (#2
) to php/security/logout.php
(we will create this file soon). We will handle the success
(#4
) and failure
(#5
) callbacks in separate functions that are declared inside the MainController
class as well. That is why the scope is set to the MainController
class (#3
) itself.
To handle the logout capability on the server, we will create a new PHP page named logout.php
under the php/security
folder. The code is very simple:
<?php session_start(); // #1 $_SESSION = array(); // #2 session_destroy(); // #3 $result = array(); // #4 $result['success'] = true; $result['msg'] = 'logout'; echo json_encode($result); // #5
First, we need to resume the current session (#1
), then we need to unset all of the session variables (#2
), and next we need to destroy the session (#3
). Lastly, we need to send the information back to Ext JS that the session has been destroyed (#4
and #5
).
We have already taken care of the server-side code. Now, we need to go back to the Ext JS code and handle the response from the server. But first, we need to understand a very important concept that usually confuses most Ext JS developers.
In Chapter 3, The Login Page, we mentioned that the ways that the form submit and Ajax requests in Ext JS handle the success x failure are a little different, and this is what confuses most developers.
The Ext.Ajax
class is responsible for Ajax requests done by Ext JS. If we look at the documentation, this class has three events: beforerequest
, requestcomplete
, and requestexception
, which are explained as follows:
beforerequest
is fired before the requestrequestcomplete
is fired when Ext JS is able to get a response from the serverrequestexception
event is fired when an HTTP error status is returned from the serverNow, let's go back to the Ext.Ajax.request
call. We can pass some options to the request, including the url
property we want to connect to, parameters, and other options including the success
and failure
functions. Now, this is where the misunderstanding begins. Some developers understand that if the action happened successfully on the server, we usually return success = true
from the server. If something goes wrong, we return success = false
. Then, on the success
function, success = true
is handled, and on the failure
function, success = false
is handled. This is wrong, and it is not how Ext JS Ajax requests work; however, that is exactly how form requests work (as we learned in Chapter 3, The Login Page). See how it gets confusing?
For Ext JS Ajax requests, success
is when the server returns a response (success
true
or false
; it does not matter), and failure
is when the server returns an HTTP error status. This means that if the server was able to return a response, we will handle this response on the success
function (and we will need to handle it whether the success
information is true
or false
), and on the failure
message, we need to inform the user that something went wrong and the user should contact the system administrator.
We will implement the failure
callback function first. So, inside the ViewController
class, we will add the following code:
onLogoutFailure: function(conn, response, options, eOpts){ Packt.util.Util.showErrorMsg(conn.responseText); },
What we are going to do is display an alert to the user with an error icon and an OK button with the HTTP status error information.
To reproduce an error so the requestexception
event can be fired, we can rename the logout.php
file to something else (for example, logout_.php
) only for testing purposes. And then, we can execute the code, and we will have the following output:
And this is all we need for the failure
function. Note that we are reusing the Packt.util.Util
class that we developed in Chapter 3, The Login Page, in this chapter again! See how it is nice to reuse code?
We are reusing code and saving some lines of duplicated code. We are also creating a pattern of how to handle a few things in our project. This is very important when working in a project, especially when working in a team. This way, the project will look like a single person and not that multiple people developed it, which is really good. This is also a best practice to be followed. Reusing code is also part of what is called minimizing the payload size, which is one of the best practices while developing with JavaScript and also a concern of web development. To learn more about this, please visit https://developers.google.com/speed/docs/best-practices/payload.
To make the code work, remove the following code from the MainController
class:
requires: [ 'Ext.MessageBox' ],
Write the following code in the preceding code's position:
requires: [
'Packt.util.Util'
],
Now, let's focus on the success
callback function:
onLogoutSuccess: function(conn, response, options, eOpts){ //#1 var result = Packt.util.Util.decodeJSON(conn.responseText); if (result.success) { //#2 this.getView().destroy(); //#3 window.location.reload(); //#4 } else { Packt.util.Util.showErrorMsg(result.msg); //#5 } }
The first thing we need to do is decode the JSON message (#1
) that we received from the server. If we log the conn
parameter sent to the success
function (console.log(conn)
), this will be the output we will get on the console:
The conn.responseText
property is where the information we want to retrieve is present, the success
and msg
values. Recall that in Chapter 3, The Login Page, we discussed the possibility of responseText
containing an exception other than the JSON we are expecting. So, for this reason, we are going to reuse the decodeJSON
function we created (#1
) so that we can properly handle any results.
In the case of success
(#2
), we are going to destroy
the Main
class (#3
), which is our Viewport (this is good to release the browser's memory and make the objects available for the JavaScript garbage collector). As the Viewport contains all the other components of our application, it is going to destroy them as well. Then, we will reload the application displaying the Login screen again (#4
).
If success
is false
(or any error occurred), we will display an error alert with the error message (#5
).
18.188.200.118