SlideShare a Scribd company logo
1 of 73
Download to read offline
Copyright © 2016 M/Gateway Developments Ltd
EWD 3 Training Course
Part 41
Building a React.js-based
QEWD Application
(e) Building out a login sequence
Rob Tweed
Director, M/Gateway Developments Ltd
Twitter: @rtweed
Copyright © 2016 M/Gateway Developments Ltd
What We Want to Do
Copyright © 2016 M/Gateway Developments Ltd
What We Want to Do
Copyright © 2016 M/Gateway Developments Ltd
What We Want to Do
Copyright © 2016 M/Gateway Developments Ltd
React.js Design
Main Page
Title / Banner Login Form Content
Copyright © 2016 M/Gateway Developments Ltd
React.js Design
Main Page
Title / Banner Login Form Content
Initially
Initial Title Display the form No Content
Copyright © 2016 M/Gateway Developments Ltd
React.js Design
Main Page
Title / Banner Login Form Content
On login error
Initial Title Display the form No Content
Display Error
Copyright © 2016 M/Gateway Developments Ltd
React.js Design
Main Page
Title / Banner Login Form Content
On Successful
login
Hello {{user}}
title
Hide the form Display
Content
Copyright © 2016 M/Gateway Developments Ltd
React.js Design
Main Page
Title / Banner Login Form Content
React.js Mechanics
Send username
& password as EWD
message
Copyright © 2016 M/Gateway Developments Ltd
React.js Design
Main Page
Title / Banner Login Form Content
React.js Mechanics
Send username
& password as EWD
message
To QEWD
Back-end
Copyright © 2016 M/Gateway Developments Ltd
React.js Design
Main Page
Title / Banner Login Form Content
React.js Mechanics
From
Back-end
Handle response
Copyright © 2016 M/Gateway Developments Ltd
React.js Design
Main Page
Title / Banner Login Form Content
React.js Mechanics
Error response
received:
Display Error
Copyright © 2016 M/Gateway Developments Ltd
React.js Design
Main Page
Title / Banner Login Form Content
React.js Mechanics
Success response
received:
Re-render
Copyright © 2016 M/Gateway Developments Ltd
React.js Design
Main Page
Title / Banner Login Form Content
React.js Mechanics
Pass down
Username as
prop
Copyright © 2016 M/Gateway Developments Ltd
React.js Design
Main Page
Title / Banner Login Form Content
React.js Mechanics
Pass prop to
Signal successful
login
Copyright © 2016 M/Gateway Developments Ltd
React.js Design
Main Page
Title / Banner Login Form Content
React.js Mechanics
Pass prop to
signal that
content should
be displayed
Copyright © 2016 M/Gateway Developments Ltd
So let's build out the components
In ~/qewd/www/react-demo1
Copyright © 2016 M/Gateway Developments Ltd
MainPage.js
"use strict"
var React = require('react');
var Title = require('./Title');
var Content = require('./Content');
var Login = require('./Login');
var jQuery = require('jquery');
window.$ = window.jQuery = jQuery;
var controller;
var MainPage = React.createClass({
getInitialState: function() {
return {
status: 'initial',
}
},
componentWillMount: function() {
controller = require('./MainPage-controller')(this.props.controller, this);
},
render: function() {
console.log('Rendering MainPage');
return (
<div>
<Title
controller = {controller}
username = {this.username}
/>
<Login
controller = {controller}
loggedIn = {this.loggedIn}
/>
<Content
controller = {controller}
content = {this.content}
/>
</div>
);
}
});
module.exports = MainPage;
Copyright © 2016 M/Gateway Developments Ltd
MainPage.js
"use strict"
var React = require('react');
var Title = require('./Title');
var Content = require('./Content');
var Login = require('./Login');
var jQuery = require('jquery');
window.$ = window.jQuery = jQuery;
var controller;
var MainPage = React.createClass({
getInitialState: function() {
return {
status: 'initial',
}
},
componentWillMount: function() {
controller = require('./MainPage-controller')(this.props.controller, this);
},
render: function() {
console.log('Rendering MainPage');
return (
<div>
<Title
controller = {controller}
username = {this.username}
/>
<Login
controller = {controller}
loggedIn = {this.loggedIn}
/>
<Content
controller = {controller}
content = {this.content}
/>
</div>
);
}
});
module.exports = MainPage;
Initial state
variable value
Copyright © 2016 M/Gateway Developments Ltd
MainPage.js
"use strict"
var React = require('react');
var Title = require('./Title');
var Content = require('./Content');
var Login = require('./Login');
var jQuery = require('jquery');
window.$ = window.jQuery = jQuery;
var controller;
var MainPage = React.createClass({
getInitialState: function() {
return {
status: 'initial',
}
},
componentWillMount: function() {
controller = require('./MainPage-controller')(this.props.controller, this);
},
render: function() {
console.log('Rendering MainPage');
return (
<div>
<Title
controller = {controller}
username = {this.username}
/>
<Login
controller = {controller}
loggedIn = {this.loggedIn}
/>
<Content
controller = {controller}
content = {this.content}
/>
</div>
);
}
});
module.exports = MainPage;
props passed
to child
components
Copyright © 2016 M/Gateway Developments Ltd
MainPage-controller.js
module.exports = function (controller, component) {
controller.log = true;
component.loggedIn = false;
component.username = '';
component.content = '';
controller.on('error', function(responseObj) {
alert('Error: ' + responseObj.message.error);
});
controller.on('login', function(responseObj) {
if (!responseObj.message.error) {
console.log('Logged in!');
component.loggedIn = true;
component.username = responseObj.message.name;
component.content = 'User has logged in - ready to display some content for the user!';
component.setState({
status: 'loggedIn'
});
}
});
return controller;
};
Copyright © 2016 M/Gateway Developments Ltd
MainPage-controller.js
module.exports = function (controller, component) {
controller.log = true;
component.loggedIn = false;
component.username = '';
component.content = '';
controller.on('error', function(responseObj) {
alert('Error: ' + responseObj.message.error);
});
controller.on('login', function(responseObj) {
if (!responseObj.message.error) {
console.log('Logged in!');
component.loggedIn = true;
component.username = responseObj.message.name;
component.content = 'User has logged in - ready to display some content for the user!';
component.setState({
status: 'loggedIn'
});
}
});
return controller;
};
Response
from back-end
handled in this
top component
Copyright © 2016 M/Gateway Developments Ltd
MainPage-controller.js
module.exports = function (controller, component) {
controller.log = true;
component.loggedIn = false;
component.username = '';
component.content = '';
controller.on('error', function(responseObj) {
alert('Error: ' + responseObj.message.error);
});
controller.on('login', function(responseObj) {
if (!responseObj.message.error) {
console.log('Logged in!');
component.loggedIn = true;
component.username = responseObj.message.name;
component.content = 'User has logged in - ready to display some content for the user!';
component.setState({
status: 'loggedIn'
});
}
});
return controller;
};
Initial values
passed as
props to child
components
Copyright © 2016 M/Gateway Developments Ltd
MainPage-controller.js
module.exports = function (controller, component) {
controller.log = true;
component.loggedIn = false;
component.username = '';
component.content = '';
controller.on('error', function(responseObj) {
alert('Error: ' + responseObj.message.error);
});
controller.on('login', function(responseObj) {
if (!responseObj.message.error) {
console.log('Logged in!');
component.loggedIn = true;
component.username = responseObj.message.name;
component.content = 'User has logged in - ready to display some content for the user!';
component.setState({
status: 'loggedIn'
});
}
});
return controller;
};
New values
passed as
props to child
components
if login is
successful
Copyright © 2016 M/Gateway Developments Ltd
MainPage-controller.js
module.exports = function (controller, component) {
controller.log = true;
component.loggedIn = false;
component.username = '';
component.content = '';
controller.on('error', function(responseObj) {
alert('Error: ' + responseObj.message.error);
});
controller.on('login', function(responseObj) {
if (!responseObj.message.error) {
console.log('Logged in!');
component.loggedIn = true;
component.username = responseObj.message.name;
component.content = 'User has logged in - ready to display some content for the user!';
component.setState({
status: 'loggedIn'
});
}
});
return controller;
};
State value
changed to
trigger
re-render of
this component
and its child
components
Copyright © 2016 M/Gateway Developments Ltd
Title.js
var React = require('react');
var controller;
var Title = React.createClass({
componentWillMount: function() {
controller = require('./Title-controller')(this.props.controller, this);
},
componentWillReceiveProps: function(newProps) {
this.updateHeading(newProps.username);
},
render: function() {
console.log('Rendering Title');
return (
<h2>
{this.heading}
</h2>
);
}
});
module.exports = Title;
Copyright © 2016 M/Gateway Developments Ltd
Title.js
var React = require('react');
var controller;
var Title = React.createClass({
componentWillMount: function() {
controller = require('./Title-controller')(this.props.controller, this);
},
componentWillReceiveProps: function(newProps) {
this.updateHeading(newProps.username);
},
render: function() {
console.log('Rendering Title');
return (
<h2>
{this.heading}
</h2>
);
}
});
module.exports = Title;
Fires if props
have changed
Does not fire
on initial render
Copyright © 2016 M/Gateway Developments Ltd
Title-controller.js
module.exports = function (controller, component) {
component.heading = 'My QEWD React Demo';
component.updateHeading = function(username) {
if (username !== '') {
component.heading = 'Welcome, ' + username + ', to ' + component.heading;
}
};
return controller;
};
Copyright © 2016 M/Gateway Developments Ltd
Login.js"use strict"
var React = require('react');
var controller;
var Login = React.createClass({
getInitialState: function() {
return {
status: 'initial',
}
},
componentWillMount: function() {
controller = require('./Login-controller')(this.props.controller, this);
},
render: function() {
console.log('rendering Login');
if (this.props.loggedIn) {
return (
<div></div>
);
}
return (
<table id="loginTable">
<tbody>
<tr>
<td>Username: </td>
<td><input id="username" /> </td>
</tr>
<tr>
<td>Password: </td>
<td><input id="password" type="password" /> </td>
</tr>
<tr>
<td colSpan="2">
<button
id="LoginBtn"
onClick={this.LoginBtnClicked}
>
Login
</button>
</td>
</tr>
</tbody>
</table>
);
}
});
module.exports = Login;
Copyright © 2016 M/Gateway Developments Ltd
Login.js"use strict"
var React = require('react');
var controller;
var Login = React.createClass({
getInitialState: function() {
return {
status: 'initial',
}
},
componentWillMount: function() {
controller = require('./Login-controller')(this.props.controller, this);
},
render: function() {
console.log('rendering Login');
if (this.props.loggedIn) {
return (
<div></div>
);
}
return (
<table id="loginTable">
<tbody>
<tr>
<td>Username: </td>
<td><input id="username" /> </td>
</tr>
<tr>
<td>Password: </td>
<td><input id="password" type="password" /> </td>
</tr>
<tr>
<td colSpan="2">
<button
id="LoginBtn"
onClick={this.LoginBtnClicked}
>
Login
</button>
</td>
</tr>
</tbody>
</table>
);
}
});
module.exports = Login;
On successful
login, display
nothing
Form disappears
Copyright © 2016 M/Gateway Developments Ltd
Login.js"use strict"
var React = require('react');
var controller;
var Login = React.createClass({
getInitialState: function() {
return {
status: 'initial',
}
},
componentWillMount: function() {
controller = require('./Login-controller')(this.props.controller, this);
},
render: function() {
console.log('rendering Login');
if (this.props.loggedIn) {
return (
<div></div>
);
}
return (
<table id="loginTable">
<tbody>
<tr>
<td>Username: </td>
<td><input id="username" /> </td>
</tr>
<tr>
<td>Password: </td>
<td><input id="password" type="password" /> </td>
</tr>
<tr>
<td colSpan="2">
<button
id="LoginBtn"
onClick={this.LoginBtnClicked}
>
Login
</button>
</td>
</tr>
</tbody>
</table>
);
}
});
module.exports = Login;
Otherwise,
display the form
Copyright © 2016 M/Gateway Developments Ltd
Login.js"use strict"
var React = require('react');
var controller;
var Login = React.createClass({
getInitialState: function() {
return {
status: 'initial',
}
},
componentWillMount: function() {
controller = require('./Login-controller')(this.props.controller, this);
},
render: function() {
console.log('rendering Login');
if (this.props.loggedIn) {
return (
<div></div>
);
}
return (
<table id="loginTable">
<tbody>
<tr>
<td>Username: </td>
<td><input id="username" /> </td>
</tr>
<tr>
<td>Password: </td>
<td><input id="password" type="password" /> </td>
</tr>
<tr>
<td colSpan="2">
<button
id="LoginBtn"
onClick={this.LoginBtnClicked}
>
Login
</button>
</td>
</tr>
</tbody>
</table>
);
}
});
module.exports = Login;
JSX Click handler
Copyright © 2016 M/Gateway Developments Ltd
Login-controller.js
module.exports = function (controller, component) {
component.LoginBtnClicked = function(e) {
var username = $('#username').val();
var password = $('#password').val();
if (username === '') {
alert('You must enter a username!');
return;
}
if (password === '') {
alert('You must enter a password!');
return;
}
controller.send({
type: 'login',
params: {
username: username,
password: password
}
});
};
return controller;
};
Copyright © 2016 M/Gateway Developments Ltd
Login-controller.js
module.exports = function (controller, component) {
component.LoginBtnClicked = function(e) {
var username = $('#username').val();
var password = $('#password').val();
if (username === '') {
alert('You must enter a username!');
return;
}
if (password === '') {
alert('You must enter a password!');
return;
}
controller.send({
type: 'login',
params: {
username: username,
password: password
}
});
};
return controller;
};
Define the
Login button's
click handler
Copyright © 2016 M/Gateway Developments Ltd
Login-controller.js
module.exports = function (controller, component) {
component.LoginBtnClicked = function(e) {
var username = $('#username').val();
var password = $('#password').val();
if (username === '') {
alert('You must enter a username!');
return;
}
if (password === '') {
alert('You must enter a password!');
return;
}
controller.send({
type: 'login',
params: {
username: username,
password: password
}
});
};
return controller;
};
Send the username
and password to
the ewd-xpress
Back-end
The response is
handled in the
Parent component
Copyright © 2016 M/Gateway Developments Ltd
Content.js
var React = require('react');
var controller;
var Content = React.createClass({
componentWillMount: function() {
controller = require('./Content-controller')(this.props.controller, this);
},
componentWillReceiveProps: function(newProps) {
this.updateContent(newProps.content);
},
render: function() {
console.log('Rendering Content');
return (
<div>
{this.content}
</div>
);
}
});
module.exports = Content;
Copyright © 2016 M/Gateway Developments Ltd
Content.js
var React = require('react');
var controller;
var Content = React.createClass({
componentWillMount: function() {
controller = require('./Content-controller')(this.props.controller, this);
},
componentWillReceiveProps: function(newProps) {
this.updateContent(newProps.content);
},
render: function() {
console.log('Rendering Content');
return (
<div>
{this.content}
</div>
);
}
});
module.exports = Content;
Simply display
the value of
this.content each
Time it renders
Copyright © 2016 M/Gateway Developments Ltd
Content.js
var React = require('react');
var controller;
var Content = React.createClass({
componentWillMount: function() {
controller = require('./Content-controller')(this.props.controller, this);
},
componentWillReceiveProps: function(newProps) {
this.updateContent(newProps.content);
},
render: function() {
console.log('Rendering Content');
return (
<div>
{this.content}
</div>
);
}
});
module.exports = Content;
Use the
componentWillReceiveProps
life-cycle method to
update the content
whenever re-rendering
occurs
Copyright © 2016 M/Gateway Developments Ltd
Content.js
var React = require('react');
var controller;
var Content = React.createClass({
componentWillMount: function() {
controller = require('./Content-controller')(this.props.controller, this);
},
componentWillReceiveProps: function(newProps) {
this.updateContent(newProps.content);
},
render: function() {
console.log('Rendering Content');
return (
<div>
{this.content}
</div>
);
}
});
module.exports = Content;
The
componentWillReceiveProps
life-cycle method will
invoke a method named
this.updateContent
We'll define it in the
content-controller module
Copyright © 2016 M/Gateway Developments Ltd
Content-controller.js
module.exports = function (controller, component) {
component.content = component.props.content;
component.updateContent = function(newContent) {
if (newContent !== '') {
component.content = newContent;
}
};
return controller;
};
Copyright © 2016 M/Gateway Developments Ltd
Content-controller.js
module.exports = function (controller, component) {
component.content = component.props.content;
component.updateContent = function(newContent) {
if (newContent !== '') {
component.content = newContent;
}
};
return controller;
};
Here's the
this.updateContent
Method
It just updates
this.content
Within the controller,
instead of this we
refer to component
Copyright © 2016 M/Gateway Developments Ltd
Finally the back-end Module
• This must handle the login message that is
sent from the browser when the Login
form button is clicked
• It must validate the username and
password
• For simplicity, we'll just hard-code the valid
values
– In a real-world app, you'd authenticate against
a database or using a dedicated API
Copyright © 2016 M/Gateway Developments Ltd
Finally the back-end Module
• It's advisable to repeat any browser-side
validation at the back-end
– A malicious user might attempt to send a login
message via the JavaScript console
• We'll authenticate the user and prevent an
already-logged in user from logging in
again
Copyright © 2016 M/Gateway Developments Ltd
Back-end module
module.exports = {
handlers: {
login: function(messageObj, session, send, finished) {
if (session.authenticated) {
finished({error: 'You have already logged in'});
return;
}
if (messageObj.params.username === '') {
finished({error: 'You must enter a username'});
return;
}
if (messageObj.params.password === '') {
finished({error: 'You must enter a password'});
return;
}
if (messageObj.params.username !== 'rob') {
finished({error: 'Invalid username'});
return;
}
if (messageObj.params.password !== 'secret') {
finished({error: 'Invalid password'});
return;
}
session.authenticated = true;
finished({
ok: true,
name: 'Rob'
});
}
}
};
~/qewd/node_modules/react-demo1.js
Copyright © 2016 M/Gateway Developments Ltd
Back-end module
module.exports = {
handlers: {
login: function(messageObj, session, send, finished) {
if (session.authenticated) {
finished({error: 'You have already logged in'});
return;
}
if (messageObj.params.username === '') {
finished({error: 'You must enter a username'});
return;
}
if (messageObj.params.password === '') {
finished({error: 'You must enter a password'});
return;
}
if (messageObj.params.username !== 'rob') {
finished({error: 'Invalid username'});
return;
}
if (messageObj.params.password !== 'secret') {
finished({error: 'Invalid password'});
return;
}
session.authenticated = true;
finished({
ok: true,
name: 'Rob'
});
}
}
};
~/qewd/node_modules/react-demo1.js
Repeat the
Browser-side
Validation
Return an error
object if it fails
Copyright © 2016 M/Gateway Developments Ltd
Back-end module
module.exports = {
handlers: {
login: function(messageObj, session, send, finished) {
if (session.authenticated) {
finished({error: 'You have already logged in'});
return;
}
if (messageObj.params.username === '') {
finished({error: 'You must enter a username'});
return;
}
if (messageObj.params.password === '') {
finished({error: 'You must enter a password'});
return;
}
if (messageObj.params.username !== 'rob') {
finished({error: 'Invalid username'});
return;
}
if (messageObj.params.password !== 'secret') {
finished({error: 'Invalid password'});
return;
}
session.authenticated = true;
finished({
ok: true,
name: 'Rob'
});
}
}
};
~/qewd/node_modules/react-demo1.js
Here's our simple
hard-coded validation
Username must be
'rob' and password
must be 'secret'
Copyright © 2016 M/Gateway Developments Ltd
Back-end module
module.exports = {
handlers: {
login: function(messageObj, session, send, finished) {
if (session.authenticated) {
finished({error: 'You have already logged in'});
return;
}
if (messageObj.params.username === '') {
finished({error: 'You must enter a username'});
return;
}
if (messageObj.params.password === '') {
finished({error: 'You must enter a password'});
return;
}
if (messageObj.params.username !== 'rob') {
finished({error: 'Invalid username'});
return;
}
if (messageObj.params.password !== 'secret') {
finished({error: 'Invalid password'});
return;
}
session.authenticated = true;
finished({
ok: true,
name: 'Rob'
});
}
}
};
~/qewd/node_modules/react-demo1.js
Set the session
authenticated
property
Copyright © 2016 M/Gateway Developments Ltd
Back-end module
module.exports = {
handlers: {
login: function(messageObj, session, send, finished) {
if (session.authenticated) {
finished({error: 'You have already logged in'});
return;
}
if (messageObj.params.username === '') {
finished({error: 'You must enter a username'});
return;
}
if (messageObj.params.password === '') {
finished({error: 'You must enter a password'});
return;
}
if (messageObj.params.username !== 'rob') {
finished({error: 'Invalid username'});
return;
}
if (messageObj.params.password !== 'secret') {
finished({error: 'Invalid password'});
return;
}
session.authenticated = true;
finished({
ok: true,
name: 'Rob'
});
}
}
};
~/qewd/node_modules/react-demo1.js
Return a user name
in the response object
This simple example uses
a hard-coded value: 'Rob'
Copyright © 2016 M/Gateway Developments Ltd
That should be it!
• Re-bundle it using Browserify in the
normal way
• Try running it!
Copyright © 2016 M/Gateway Developments Ltd
Try it
Copyright © 2016 M/Gateway Developments Ltd
React.js Design
Main Page
Title / Banner Login Form Content
Initially
Initial Title Display the form No Content
Copyright © 2016 M/Gateway Developments Ltd
Login with wrong credentials
Copyright © 2016 M/Gateway Developments Ltd
React.js Design
Main Page
Title / Banner Login Form Content
On login error
Initial Title Display the form No Content
Display Error
Copyright © 2016 M/Gateway Developments Ltd
Successful login
Username: rob ; password: secret
Copyright © 2016 M/Gateway Developments Ltd
React.js Design
Main Page
Title / Banner Login Form Content
On Successful
login
Hello {{user}}
title
Hide the form Display
Content
Copyright © 2016 M/Gateway Developments Ltd
How that happened
Copyright © 2016 M/Gateway Developments Ltd
React.js Design
Main Page
Title / Banner Login Form Content
React.js Mechanics
Send username
& password as EWD
message
Copyright © 2016 M/Gateway Developments Ltd
Login-controller.js
module.exports = function (controller, component) {
component.LoginBtnClicked = function(e) {
var username = $('#username').val();
var password = $('#password').val();
if (username === '') {
alert('You must enter a username!');
return;
}
if (password === '') {
alert('You must enter a password!');
return;
}
controller.send({
type: 'login',
params: {
username: username,
password: password
}
});
};
return controller;
};
Define the
Login button's
click handler
Copyright © 2016 M/Gateway Developments Ltd
Login-controller.js
module.exports = function (controller, component) {
component.LoginBtnClicked = function(e) {
var username = $('#username').val();
var password = $('#password').val();
if (username === '') {
alert('You must enter a username!');
return;
}
if (password === '') {
alert('You must enter a password!');
return;
}
controller.send({
type: 'login',
params: {
username: username,
password: password
}
});
};
return controller;
};
Send the username
and password to
the ewd-xpress
Back-end
The response is
handled in the
Parent component
Copyright © 2016 M/Gateway Developments Ltd
React.js Design
Main Page
Title / Banner Login Form Content
React.js Mechanics
Send username
& password as EWD
message
To Back-end
module:
react-demo1.js
Copyright © 2016 M/Gateway Developments Ltd
Back-end module
module.exports = {
handlers: {
login: function(messageObj, session, send, finished) {
if (session.authenticated) {
finished({error: 'You have already logged in'});
return;
}
if (messageObj.params.username === '') {
finished({error: 'You must enter a username'});
return;
}
if (messageObj.params.password === '') {
finished({error: 'You must enter a password'});
return;
}
if (messageObj.params.username !== 'rob') {
finished({error: 'Invalid username'});
return;
}
if (messageObj.params.password !== 'secret') {
finished({error: 'Invalid password'});
return;
}
session.authenticated = true;
finished({
ok: true,
name: 'Rob'
});
}
}
};
~/qewd/node_modules/react-demo1.js
Here's our simple
hard-coded validation
Username must be
'rob' and password
must be 'secret'
Copyright © 2016 M/Gateway Developments Ltd
React.js Design
Main Page
Title / Banner Login Form Content
React.js Mechanics
From
Back-end
Handle response
Copyright © 2016 M/Gateway Developments Ltd
MainPage-controller.js
module.exports = function (controller, component) {
controller.log = true;
component.loggedIn = false;
component.username = '';
component.content = '';
controller.on('error', function(responseObj) {
alert('Error: ' + responseObj.message.error);
});
controller.on('login', function(responseObj) {
if (!responseObj.message.error) {
console.log('Logged in!');
component.loggedIn = true;
component.username = responseObj.message.name;
component.content = 'User has logged in - ready to display some content for the user!';
component.setState({
status: 'loggedIn'
});
}
});
return controller;
};
error handler displays
alerts
Copyright © 2016 M/Gateway Developments Ltd
React.js Design
Main Page
Title / Banner Login Form Content
React.js Mechanics
Error response
received:
Display Error
Copyright © 2016 M/Gateway Developments Ltd
MainPage-controller.js
module.exports = function (controller, component) {
controller.log = true;
component.loggedIn = false;
component.username = '';
component.content = '';
controller.on('error', function(responseObj) {
alert('Error: ' + responseObj.message.error);
});
controller.on('login', function(responseObj) {
if (!responseObj.message.error) {
console.log('Logged in!');
component.loggedIn = true;
component.username = responseObj.message.name;
component.content = 'User has logged in - ready to display some content for the user!';
component.setState({
status: 'loggedIn'
});
}
});
return controller;
};
login handler deals
with successful
logins
Copyright © 2016 M/Gateway Developments Ltd
MainPage-controller.js
module.exports = function (controller, component) {
controller.log = true;
component.loggedIn = false;
component.username = '';
component.content = '';
controller.on('error', function(responseObj) {
alert('Error: ' + responseObj.message.error);
});
controller.on('login', function(responseObj) {
if (!responseObj.message.error) {
console.log('Logged in!');
component.loggedIn = true;
component.username = responseObj.message.name;
component.content = 'User has logged in - ready to display some content for the user!';
component.setState({
status: 'loggedIn'
});
}
});
return controller;
};
New values
passed as
props to child
components
if login is
successful
Copyright © 2016 M/Gateway Developments Ltd
MainPage-controller.js
module.exports = function (controller, component) {
controller.log = true;
component.loggedIn = false;
component.username = '';
component.content = '';
controller.on('error', function(responseObj) {
alert('Error: ' + responseObj.message.error);
});
controller.on('login', function(responseObj) {
if (!responseObj.message.error) {
console.log('Logged in!');
component.loggedIn = true;
component.username = responseObj.message.name;
component.content = 'User has logged in - ready to display some content for the user!';
component.setState({
status: 'loggedIn'
});
}
});
return controller;
};
State value
changed to
trigger
re-render of
this component
and its child
components
Copyright © 2016 M/Gateway Developments Ltd
React.js Design
Main Page
Title / Banner Login Form Content
React.js Mechanics
Success response
received:
Re-render
Copyright © 2016 M/Gateway Developments Ltd
MainPage.js
"use strict"
var React = require('react');
var Title = require('./Title');
var Content = require('./Content');
var Login = require('./Login');
var jQuery = require('jquery');
window.$ = window.jQuery = jQuery;
var controller;
var MainPage = React.createClass({
getInitialState: function() {
return {
status: 'initial',
}
},
componentWillMount: function() {
controller = require('./MainPage-controller')(this.props.controller, this);
},
render: function() {
console.log('Rendering MainPage');
return (
<div>
<Title
controller = {controller}
username = {this.username}
/>
<Login
controller = {controller}
loggedIn = {this.loggedIn}
/>
<Content
controller = {controller}
content = {this.content}
/>
</div>
);
}
});
module.exports = MainPage;
props passed
to child
components
Copyright © 2016 M/Gateway Developments Ltd
React.js Design
Main Page
Title / Banner Login Form Content
React.js Mechanics
Pass down
Username as
prop
Copyright © 2016 M/Gateway Developments Ltd
React.js Design
Main Page
Title / Banner Login Form Content
React.js Mechanics
Pass prop to
Signal successful
login
Copyright © 2016 M/Gateway Developments Ltd
React.js Design
Main Page
Title / Banner Login Form Content
React.js Mechanics
Pass prop to
signal that
content should
be displayed
Copyright © 2016 M/Gateway Developments Ltd
And so we have a working demo!
Username: rob ; password: secret

More Related Content

What's hot

What's hot (20)

EWD 3 Training Course Part 36: Accessing REST and Web Services from a QEWD ap...
EWD 3 Training Course Part 36: Accessing REST and Web Services from a QEWD ap...EWD 3 Training Course Part 36: Accessing REST and Web Services from a QEWD ap...
EWD 3 Training Course Part 36: Accessing REST and Web Services from a QEWD ap...
 
EWD 3 Training Course Part 7: Applying the QEWD Messaging Pattern
EWD 3 Training Course Part 7: Applying the QEWD Messaging PatternEWD 3 Training Course Part 7: Applying the QEWD Messaging Pattern
EWD 3 Training Course Part 7: Applying the QEWD Messaging Pattern
 
EWD 3 Training Course Part 37: Building a React.js application with ewd-xpres...
EWD 3 Training Course Part 37: Building a React.js application with ewd-xpres...EWD 3 Training Course Part 37: Building a React.js application with ewd-xpres...
EWD 3 Training Course Part 37: Building a React.js application with ewd-xpres...
 
EWD 3 Training Course Part 11: Handling Errors in QEWD
EWD 3 Training Course Part 11: Handling Errors in QEWDEWD 3 Training Course Part 11: Handling Errors in QEWD
EWD 3 Training Course Part 11: Handling Errors in QEWD
 
EWD 3 Training Course Part 10: QEWD Sessions and User Authentication
EWD 3 Training Course Part 10: QEWD Sessions and User AuthenticationEWD 3 Training Course Part 10: QEWD Sessions and User Authentication
EWD 3 Training Course Part 10: QEWD Sessions and User Authentication
 
EWD 3 Training Course Part 30: Modularising QEWD Applications
EWD 3 Training Course Part 30: Modularising QEWD ApplicationsEWD 3 Training Course Part 30: Modularising QEWD Applications
EWD 3 Training Course Part 30: Modularising QEWD Applications
 
EWD 3 Training Course Part 12: QEWD Session Timeout Control
EWD 3 Training Course Part 12: QEWD Session Timeout ControlEWD 3 Training Course Part 12: QEWD Session Timeout Control
EWD 3 Training Course Part 12: QEWD Session Timeout Control
 
EWD 3 Training Course Part 29: Running QEWD as a Service
EWD 3 Training Course Part 29: Running QEWD as a ServiceEWD 3 Training Course Part 29: Running QEWD as a Service
EWD 3 Training Course Part 29: Running QEWD as a Service
 
EWD 3 Training Course Part 19: The cache.node APIs
EWD 3 Training Course Part 19: The cache.node APIsEWD 3 Training Course Part 19: The cache.node APIs
EWD 3 Training Course Part 19: The cache.node APIs
 
Micronaut For Single Page Apps
Micronaut For Single Page AppsMicronaut For Single Page Apps
Micronaut For Single Page Apps
 
React js
React jsReact js
React js
 
Angular beans
Angular beansAngular beans
Angular beans
 
EWD 3 Training Course Part 35: QEWD Session Locking
EWD 3 Training Course Part 35: QEWD Session LockingEWD 3 Training Course Part 35: QEWD Session Locking
EWD 3 Training Course Part 35: QEWD Session Locking
 
Dsc Charusat Learning React Part 1
Dsc Charusat Learning React Part 1 Dsc Charusat Learning React Part 1
Dsc Charusat Learning React Part 1
 
Getting Started with React v16
Getting Started with React v16Getting Started with React v16
Getting Started with React v16
 
Fullstack End-to-end test automation with Node.js, one year later
Fullstack End-to-end test automation with Node.js, one year laterFullstack End-to-end test automation with Node.js, one year later
Fullstack End-to-end test automation with Node.js, one year later
 
Node JS Express : Steps to Create Restful Web App
Node JS Express : Steps to Create Restful Web AppNode JS Express : Steps to Create Restful Web App
Node JS Express : Steps to Create Restful Web App
 
Serverless Java on Kubernetes
Serverless Java on KubernetesServerless Java on Kubernetes
Serverless Java on Kubernetes
 
Node.js and Selenium Webdriver, a journey from the Java side
Node.js and Selenium Webdriver, a journey from the Java sideNode.js and Selenium Webdriver, a journey from the Java side
Node.js and Selenium Webdriver, a journey from the Java side
 
Intro to ReactJS
Intro to ReactJSIntro to ReactJS
Intro to ReactJS
 

Viewers also liked

Viewers also liked (17)

EWD 3 Training Course Part 4: Installing & Configuring QEWD
EWD 3 Training Course Part 4: Installing & Configuring QEWDEWD 3 Training Course Part 4: Installing & Configuring QEWD
EWD 3 Training Course Part 4: Installing & Configuring QEWD
 
EWD 3 Training Course Part 26: Event-driven Indexing
EWD 3 Training Course Part 26: Event-driven IndexingEWD 3 Training Course Part 26: Event-driven Indexing
EWD 3 Training Course Part 26: Event-driven Indexing
 
EWD 3 Training Course Part 27: The QEWD Session
EWD 3 Training Course Part 27: The QEWD SessionEWD 3 Training Course Part 27: The QEWD Session
EWD 3 Training Course Part 27: The QEWD Session
 
EWD 3 Training Course Part 28: Integrating Legacy Mumps Code with QEWD
EWD 3 Training Course Part 28: Integrating Legacy Mumps Code with QEWDEWD 3 Training Course Part 28: Integrating Legacy Mumps Code with QEWD
EWD 3 Training Course Part 28: Integrating Legacy Mumps Code with QEWD
 
EWD 3 Training Course Part 18: Modelling NoSQL Databases using Global Storage
EWD 3 Training Course Part 18: Modelling NoSQL Databases using Global StorageEWD 3 Training Course Part 18: Modelling NoSQL Databases using Global Storage
EWD 3 Training Course Part 18: Modelling NoSQL Databases using Global Storage
 
EWD 3 Training Course Part 24: Traversing a Document's Leaf Nodes
EWD 3 Training Course Part 24: Traversing a Document's Leaf NodesEWD 3 Training Course Part 24: Traversing a Document's Leaf Nodes
EWD 3 Training Course Part 24: Traversing a Document's Leaf Nodes
 
EWD 3 Training Course Part 25: Document Database Capabilities
EWD 3 Training Course Part 25: Document Database CapabilitiesEWD 3 Training Course Part 25: Document Database Capabilities
EWD 3 Training Course Part 25: Document Database Capabilities
 
EWD 3 Training Course Part 32: Configuring QEWD to use SSL/HTTPS
EWD 3 Training Course Part 32: Configuring QEWD to use SSL/HTTPSEWD 3 Training Course Part 32: Configuring QEWD to use SSL/HTTPS
EWD 3 Training Course Part 32: Configuring QEWD to use SSL/HTTPS
 
EWD 3 Training Course Part 1: How Node.js Integrates With Global Storage Data...
EWD 3 Training Course Part 1: How Node.js Integrates With Global Storage Data...EWD 3 Training Course Part 1: How Node.js Integrates With Global Storage Data...
EWD 3 Training Course Part 1: How Node.js Integrates With Global Storage Data...
 
EWD 3 Training Course Part 21: Persistent JavaScript Objects
EWD 3 Training Course Part 21: Persistent JavaScript ObjectsEWD 3 Training Course Part 21: Persistent JavaScript Objects
EWD 3 Training Course Part 21: Persistent JavaScript Objects
 
EWD 3 Training Course Part 20: The DocumentNode Object
EWD 3 Training Course Part 20: The DocumentNode ObjectEWD 3 Training Course Part 20: The DocumentNode Object
EWD 3 Training Course Part 20: The DocumentNode Object
 
EWD 3 Training Course Part 33: Configuring QEWD to use CORS
EWD 3 Training Course Part 33: Configuring QEWD to use CORSEWD 3 Training Course Part 33: Configuring QEWD to use CORS
EWD 3 Training Course Part 33: Configuring QEWD to use CORS
 
Modern Web App Development using ClojureScript & React.js / Baishampayan “BG”...
Modern Web App Development using ClojureScript & React.js / Baishampayan “BG”...Modern Web App Development using ClojureScript & React.js / Baishampayan “BG”...
Modern Web App Development using ClojureScript & React.js / Baishampayan “BG”...
 
EWD 3 Training Course Part 22: Traversing Documents using DocumentNode Objects
EWD 3 Training Course Part 22: Traversing Documents using DocumentNode ObjectsEWD 3 Training Course Part 22: Traversing Documents using DocumentNode Objects
EWD 3 Training Course Part 22: Traversing Documents using DocumentNode Objects
 
EWD 3 Training Course Part 31: Using QEWD for Web and REST Services
EWD 3 Training Course Part 31: Using QEWD for Web and REST ServicesEWD 3 Training Course Part 31: Using QEWD for Web and REST Services
EWD 3 Training Course Part 31: Using QEWD for Web and REST Services
 
EWD 3 Training Course Part 17: Introduction to Global Storage Databases
EWD 3 Training Course Part 17: Introduction to Global Storage DatabasesEWD 3 Training Course Part 17: Introduction to Global Storage Databases
EWD 3 Training Course Part 17: Introduction to Global Storage Databases
 
EWD 3 Training Course Part 15: Using a Framework other than jQuery with QEWD
EWD 3 Training Course Part 15: Using a Framework other than jQuery with QEWDEWD 3 Training Course Part 15: Using a Framework other than jQuery with QEWD
EWD 3 Training Course Part 15: Using a Framework other than jQuery with QEWD
 

Similar to EWD 3 Training Course Part 41: Building a React.js application with QEWD, Part 5

Avinash Kundaliya: Javascript and WordPress
Avinash Kundaliya: Javascript and WordPressAvinash Kundaliya: Javascript and WordPress
Avinash Kundaliya: Javascript and WordPress
wpnepal
 

Similar to EWD 3 Training Course Part 41: Building a React.js application with QEWD, Part 5 (20)

Mobile Open Day: React Native: Crossplatform fast dive
Mobile Open Day: React Native: Crossplatform fast diveMobile Open Day: React Native: Crossplatform fast dive
Mobile Open Day: React Native: Crossplatform fast dive
 
Beginner’s tutorial (part 2) how to integrate redux-saga in react native app
Beginner’s tutorial (part 2) how to integrate redux-saga in react native appBeginner’s tutorial (part 2) how to integrate redux-saga in react native app
Beginner’s tutorial (part 2) how to integrate redux-saga in react native app
 
Introduction to React for Frontend Developers
Introduction to React for Frontend DevelopersIntroduction to React for Frontend Developers
Introduction to React for Frontend Developers
 
React outbox
React outboxReact outbox
React outbox
 
React & Redux for noobs
React & Redux for noobsReact & Redux for noobs
React & Redux for noobs
 
JSLab. Алексей Волков. "React на практике"
JSLab. Алексей Волков. "React на практике"JSLab. Алексей Волков. "React на практике"
JSLab. Алексей Волков. "React на практике"
 
Checkout Customizations in Magento 2 - MageTitansMCR 2017
Checkout Customizations in Magento 2 - MageTitansMCR 2017Checkout Customizations in Magento 2 - MageTitansMCR 2017
Checkout Customizations in Magento 2 - MageTitansMCR 2017
 
Intro react js
Intro react jsIntro react js
Intro react js
 
Server side rendering with React and Symfony
Server side rendering with React and SymfonyServer side rendering with React and Symfony
Server side rendering with React and Symfony
 
Advanced SharePoint Web Part Development
Advanced SharePoint Web Part DevelopmentAdvanced SharePoint Web Part Development
Advanced SharePoint Web Part Development
 
Hybrid App using WordPress
Hybrid App using WordPressHybrid App using WordPress
Hybrid App using WordPress
 
Web Components for Java Developers
Web Components for Java DevelopersWeb Components for Java Developers
Web Components for Java Developers
 
WCMTL 15 - Create your own shortcode (Fr)
WCMTL 15 - Create your own shortcode (Fr)WCMTL 15 - Create your own shortcode (Fr)
WCMTL 15 - Create your own shortcode (Fr)
 
Apache Aries Blog Sample
Apache Aries Blog SampleApache Aries Blog Sample
Apache Aries Blog Sample
 
The WebView Role in Hybrid Applications
The WebView Role in Hybrid ApplicationsThe WebView Role in Hybrid Applications
The WebView Role in Hybrid Applications
 
Avinash Kundaliya: Javascript and WordPress
Avinash Kundaliya: Javascript and WordPressAvinash Kundaliya: Javascript and WordPress
Avinash Kundaliya: Javascript and WordPress
 
Gutenberg sous le capot, modules réutilisables
Gutenberg sous le capot, modules réutilisablesGutenberg sous le capot, modules réutilisables
Gutenberg sous le capot, modules réutilisables
 
Rails is not just Ruby
Rails is not just RubyRails is not just Ruby
Rails is not just Ruby
 
Academy PRO: React JS
Academy PRO: React JSAcademy PRO: React JS
Academy PRO: React JS
 
Academy PRO: React native - building first scenes
Academy PRO: React native - building first scenesAcademy PRO: React native - building first scenes
Academy PRO: React native - building first scenes
 

More from Rob Tweed

More from Rob Tweed (13)

QEWD Update
QEWD UpdateQEWD Update
QEWD Update
 
Data Persistence as a Language Feature
Data Persistence as a Language FeatureData Persistence as a Language Feature
Data Persistence as a Language Feature
 
LNUG: Having Your Node.js Cake and Eating It Too
LNUG: Having Your Node.js Cake and Eating It TooLNUG: Having Your Node.js Cake and Eating It Too
LNUG: Having Your Node.js Cake and Eating It Too
 
EWD 3 Training Course Part 45: Using QEWD's Advanced MicroService Functionality
EWD 3 Training Course Part 45: Using QEWD's Advanced MicroService FunctionalityEWD 3 Training Course Part 45: Using QEWD's Advanced MicroService Functionality
EWD 3 Training Course Part 45: Using QEWD's Advanced MicroService Functionality
 
EWD 3 Training Course Part 44: Creating MicroServices with QEWD.js
EWD 3 Training Course Part 44: Creating MicroServices with QEWD.jsEWD 3 Training Course Part 44: Creating MicroServices with QEWD.js
EWD 3 Training Course Part 44: Creating MicroServices with QEWD.js
 
EWD 3 Training Course Part 43: Using JSON Web Tokens with QEWD REST Services
EWD 3 Training Course Part 43: Using JSON Web Tokens with QEWD REST ServicesEWD 3 Training Course Part 43: Using JSON Web Tokens with QEWD REST Services
EWD 3 Training Course Part 43: Using JSON Web Tokens with QEWD REST Services
 
QEWD.js, JSON Web Tokens & MicroServices
QEWD.js, JSON Web Tokens & MicroServicesQEWD.js, JSON Web Tokens & MicroServices
QEWD.js, JSON Web Tokens & MicroServices
 
QEWD.js: Have your Node.js Cake and Eat It Too
QEWD.js: Have your Node.js Cake and Eat It TooQEWD.js: Have your Node.js Cake and Eat It Too
QEWD.js: Have your Node.js Cake and Eat It Too
 
ewd-qoper8-vistarpc: Exposing VistA's RPCs as REST Services
ewd-qoper8-vistarpc: Exposing VistA's RPCs as REST Servicesewd-qoper8-vistarpc: Exposing VistA's RPCs as REST Services
ewd-qoper8-vistarpc: Exposing VistA's RPCs as REST Services
 
qewd-ripple: The Ripple OSI Middle Tier
qewd-ripple: The Ripple OSI Middle Tierqewd-ripple: The Ripple OSI Middle Tier
qewd-ripple: The Ripple OSI Middle Tier
 
EWD 3 Training Course Part 42: The QEWD Docker Appliance
EWD 3 Training Course Part 42: The QEWD Docker ApplianceEWD 3 Training Course Part 42: The QEWD Docker Appliance
EWD 3 Training Course Part 42: The QEWD Docker Appliance
 
EWD 3 Training Course Part 34: QEWD Resilient Mode
EWD 3 Training Course Part 34: QEWD Resilient ModeEWD 3 Training Course Part 34: QEWD Resilient Mode
EWD 3 Training Course Part 34: QEWD Resilient Mode
 
EWD 3 Training Course Part 23: Traversing a Range using DocumentNode Objects
EWD 3 Training Course Part 23: Traversing a Range using DocumentNode ObjectsEWD 3 Training Course Part 23: Traversing a Range using DocumentNode Objects
EWD 3 Training Course Part 23: Traversing a Range using DocumentNode Objects
 

Recently uploaded

AI Mastery 201: Elevating Your Workflow with Advanced LLM Techniques
AI Mastery 201: Elevating Your Workflow with Advanced LLM TechniquesAI Mastery 201: Elevating Your Workflow with Advanced LLM Techniques
AI Mastery 201: Elevating Your Workflow with Advanced LLM Techniques
VictorSzoltysek
 
CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICECHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
9953056974 Low Rate Call Girls In Saket, Delhi NCR
 
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
Health
 
introduction-to-automotive Andoid os-csimmonds-ndctechtown-2021.pdf
introduction-to-automotive Andoid os-csimmonds-ndctechtown-2021.pdfintroduction-to-automotive Andoid os-csimmonds-ndctechtown-2021.pdf
introduction-to-automotive Andoid os-csimmonds-ndctechtown-2021.pdf
VishalKumarJha10
 
TECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service providerTECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service provider
mohitmore19
 

Recently uploaded (20)

Optimizing AI for immediate response in Smart CCTV
Optimizing AI for immediate response in Smart CCTVOptimizing AI for immediate response in Smart CCTV
Optimizing AI for immediate response in Smart CCTV
 
AI Mastery 201: Elevating Your Workflow with Advanced LLM Techniques
AI Mastery 201: Elevating Your Workflow with Advanced LLM TechniquesAI Mastery 201: Elevating Your Workflow with Advanced LLM Techniques
AI Mastery 201: Elevating Your Workflow with Advanced LLM Techniques
 
VTU technical seminar 8Th Sem on Scikit-learn
VTU technical seminar 8Th Sem on Scikit-learnVTU technical seminar 8Th Sem on Scikit-learn
VTU technical seminar 8Th Sem on Scikit-learn
 
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
 
CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICECHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
 
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
 
Azure_Native_Qumulo_High_Performance_Compute_Benchmarks.pdf
Azure_Native_Qumulo_High_Performance_Compute_Benchmarks.pdfAzure_Native_Qumulo_High_Performance_Compute_Benchmarks.pdf
Azure_Native_Qumulo_High_Performance_Compute_Benchmarks.pdf
 
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...
 
OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...
OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...
OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...
 
Software Quality Assurance Interview Questions
Software Quality Assurance Interview QuestionsSoftware Quality Assurance Interview Questions
Software Quality Assurance Interview Questions
 
Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...
Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...
Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...
 
introduction-to-automotive Andoid os-csimmonds-ndctechtown-2021.pdf
introduction-to-automotive Andoid os-csimmonds-ndctechtown-2021.pdfintroduction-to-automotive Andoid os-csimmonds-ndctechtown-2021.pdf
introduction-to-automotive Andoid os-csimmonds-ndctechtown-2021.pdf
 
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
 
The Top App Development Trends Shaping the Industry in 2024-25 .pdf
The Top App Development Trends Shaping the Industry in 2024-25 .pdfThe Top App Development Trends Shaping the Industry in 2024-25 .pdf
The Top App Development Trends Shaping the Industry in 2024-25 .pdf
 
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
 
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdfLearn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
 
The Ultimate Test Automation Guide_ Best Practices and Tips.pdf
The Ultimate Test Automation Guide_ Best Practices and Tips.pdfThe Ultimate Test Automation Guide_ Best Practices and Tips.pdf
The Ultimate Test Automation Guide_ Best Practices and Tips.pdf
 
TECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service providerTECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service provider
 
Sector 18, Noida Call girls :8448380779 Model Escorts | 100% verified
Sector 18, Noida Call girls :8448380779 Model Escorts | 100% verifiedSector 18, Noida Call girls :8448380779 Model Escorts | 100% verified
Sector 18, Noida Call girls :8448380779 Model Escorts | 100% verified
 
Introducing Microsoft’s new Enterprise Work Management (EWM) Solution
Introducing Microsoft’s new Enterprise Work Management (EWM) SolutionIntroducing Microsoft’s new Enterprise Work Management (EWM) Solution
Introducing Microsoft’s new Enterprise Work Management (EWM) Solution
 

EWD 3 Training Course Part 41: Building a React.js application with QEWD, Part 5

  • 1. Copyright © 2016 M/Gateway Developments Ltd EWD 3 Training Course Part 41 Building a React.js-based QEWD Application (e) Building out a login sequence Rob Tweed Director, M/Gateway Developments Ltd Twitter: @rtweed
  • 2. Copyright © 2016 M/Gateway Developments Ltd What We Want to Do
  • 3. Copyright © 2016 M/Gateway Developments Ltd What We Want to Do
  • 4. Copyright © 2016 M/Gateway Developments Ltd What We Want to Do
  • 5. Copyright © 2016 M/Gateway Developments Ltd React.js Design Main Page Title / Banner Login Form Content
  • 6. Copyright © 2016 M/Gateway Developments Ltd React.js Design Main Page Title / Banner Login Form Content Initially Initial Title Display the form No Content
  • 7. Copyright © 2016 M/Gateway Developments Ltd React.js Design Main Page Title / Banner Login Form Content On login error Initial Title Display the form No Content Display Error
  • 8. Copyright © 2016 M/Gateway Developments Ltd React.js Design Main Page Title / Banner Login Form Content On Successful login Hello {{user}} title Hide the form Display Content
  • 9. Copyright © 2016 M/Gateway Developments Ltd React.js Design Main Page Title / Banner Login Form Content React.js Mechanics Send username & password as EWD message
  • 10. Copyright © 2016 M/Gateway Developments Ltd React.js Design Main Page Title / Banner Login Form Content React.js Mechanics Send username & password as EWD message To QEWD Back-end
  • 11. Copyright © 2016 M/Gateway Developments Ltd React.js Design Main Page Title / Banner Login Form Content React.js Mechanics From Back-end Handle response
  • 12. Copyright © 2016 M/Gateway Developments Ltd React.js Design Main Page Title / Banner Login Form Content React.js Mechanics Error response received: Display Error
  • 13. Copyright © 2016 M/Gateway Developments Ltd React.js Design Main Page Title / Banner Login Form Content React.js Mechanics Success response received: Re-render
  • 14. Copyright © 2016 M/Gateway Developments Ltd React.js Design Main Page Title / Banner Login Form Content React.js Mechanics Pass down Username as prop
  • 15. Copyright © 2016 M/Gateway Developments Ltd React.js Design Main Page Title / Banner Login Form Content React.js Mechanics Pass prop to Signal successful login
  • 16. Copyright © 2016 M/Gateway Developments Ltd React.js Design Main Page Title / Banner Login Form Content React.js Mechanics Pass prop to signal that content should be displayed
  • 17. Copyright © 2016 M/Gateway Developments Ltd So let's build out the components In ~/qewd/www/react-demo1
  • 18. Copyright © 2016 M/Gateway Developments Ltd MainPage.js "use strict" var React = require('react'); var Title = require('./Title'); var Content = require('./Content'); var Login = require('./Login'); var jQuery = require('jquery'); window.$ = window.jQuery = jQuery; var controller; var MainPage = React.createClass({ getInitialState: function() { return { status: 'initial', } }, componentWillMount: function() { controller = require('./MainPage-controller')(this.props.controller, this); }, render: function() { console.log('Rendering MainPage'); return ( <div> <Title controller = {controller} username = {this.username} /> <Login controller = {controller} loggedIn = {this.loggedIn} /> <Content controller = {controller} content = {this.content} /> </div> ); } }); module.exports = MainPage;
  • 19. Copyright © 2016 M/Gateway Developments Ltd MainPage.js "use strict" var React = require('react'); var Title = require('./Title'); var Content = require('./Content'); var Login = require('./Login'); var jQuery = require('jquery'); window.$ = window.jQuery = jQuery; var controller; var MainPage = React.createClass({ getInitialState: function() { return { status: 'initial', } }, componentWillMount: function() { controller = require('./MainPage-controller')(this.props.controller, this); }, render: function() { console.log('Rendering MainPage'); return ( <div> <Title controller = {controller} username = {this.username} /> <Login controller = {controller} loggedIn = {this.loggedIn} /> <Content controller = {controller} content = {this.content} /> </div> ); } }); module.exports = MainPage; Initial state variable value
  • 20. Copyright © 2016 M/Gateway Developments Ltd MainPage.js "use strict" var React = require('react'); var Title = require('./Title'); var Content = require('./Content'); var Login = require('./Login'); var jQuery = require('jquery'); window.$ = window.jQuery = jQuery; var controller; var MainPage = React.createClass({ getInitialState: function() { return { status: 'initial', } }, componentWillMount: function() { controller = require('./MainPage-controller')(this.props.controller, this); }, render: function() { console.log('Rendering MainPage'); return ( <div> <Title controller = {controller} username = {this.username} /> <Login controller = {controller} loggedIn = {this.loggedIn} /> <Content controller = {controller} content = {this.content} /> </div> ); } }); module.exports = MainPage; props passed to child components
  • 21. Copyright © 2016 M/Gateway Developments Ltd MainPage-controller.js module.exports = function (controller, component) { controller.log = true; component.loggedIn = false; component.username = ''; component.content = ''; controller.on('error', function(responseObj) { alert('Error: ' + responseObj.message.error); }); controller.on('login', function(responseObj) { if (!responseObj.message.error) { console.log('Logged in!'); component.loggedIn = true; component.username = responseObj.message.name; component.content = 'User has logged in - ready to display some content for the user!'; component.setState({ status: 'loggedIn' }); } }); return controller; };
  • 22. Copyright © 2016 M/Gateway Developments Ltd MainPage-controller.js module.exports = function (controller, component) { controller.log = true; component.loggedIn = false; component.username = ''; component.content = ''; controller.on('error', function(responseObj) { alert('Error: ' + responseObj.message.error); }); controller.on('login', function(responseObj) { if (!responseObj.message.error) { console.log('Logged in!'); component.loggedIn = true; component.username = responseObj.message.name; component.content = 'User has logged in - ready to display some content for the user!'; component.setState({ status: 'loggedIn' }); } }); return controller; }; Response from back-end handled in this top component
  • 23. Copyright © 2016 M/Gateway Developments Ltd MainPage-controller.js module.exports = function (controller, component) { controller.log = true; component.loggedIn = false; component.username = ''; component.content = ''; controller.on('error', function(responseObj) { alert('Error: ' + responseObj.message.error); }); controller.on('login', function(responseObj) { if (!responseObj.message.error) { console.log('Logged in!'); component.loggedIn = true; component.username = responseObj.message.name; component.content = 'User has logged in - ready to display some content for the user!'; component.setState({ status: 'loggedIn' }); } }); return controller; }; Initial values passed as props to child components
  • 24. Copyright © 2016 M/Gateway Developments Ltd MainPage-controller.js module.exports = function (controller, component) { controller.log = true; component.loggedIn = false; component.username = ''; component.content = ''; controller.on('error', function(responseObj) { alert('Error: ' + responseObj.message.error); }); controller.on('login', function(responseObj) { if (!responseObj.message.error) { console.log('Logged in!'); component.loggedIn = true; component.username = responseObj.message.name; component.content = 'User has logged in - ready to display some content for the user!'; component.setState({ status: 'loggedIn' }); } }); return controller; }; New values passed as props to child components if login is successful
  • 25. Copyright © 2016 M/Gateway Developments Ltd MainPage-controller.js module.exports = function (controller, component) { controller.log = true; component.loggedIn = false; component.username = ''; component.content = ''; controller.on('error', function(responseObj) { alert('Error: ' + responseObj.message.error); }); controller.on('login', function(responseObj) { if (!responseObj.message.error) { console.log('Logged in!'); component.loggedIn = true; component.username = responseObj.message.name; component.content = 'User has logged in - ready to display some content for the user!'; component.setState({ status: 'loggedIn' }); } }); return controller; }; State value changed to trigger re-render of this component and its child components
  • 26. Copyright © 2016 M/Gateway Developments Ltd Title.js var React = require('react'); var controller; var Title = React.createClass({ componentWillMount: function() { controller = require('./Title-controller')(this.props.controller, this); }, componentWillReceiveProps: function(newProps) { this.updateHeading(newProps.username); }, render: function() { console.log('Rendering Title'); return ( <h2> {this.heading} </h2> ); } }); module.exports = Title;
  • 27. Copyright © 2016 M/Gateway Developments Ltd Title.js var React = require('react'); var controller; var Title = React.createClass({ componentWillMount: function() { controller = require('./Title-controller')(this.props.controller, this); }, componentWillReceiveProps: function(newProps) { this.updateHeading(newProps.username); }, render: function() { console.log('Rendering Title'); return ( <h2> {this.heading} </h2> ); } }); module.exports = Title; Fires if props have changed Does not fire on initial render
  • 28. Copyright © 2016 M/Gateway Developments Ltd Title-controller.js module.exports = function (controller, component) { component.heading = 'My QEWD React Demo'; component.updateHeading = function(username) { if (username !== '') { component.heading = 'Welcome, ' + username + ', to ' + component.heading; } }; return controller; };
  • 29. Copyright © 2016 M/Gateway Developments Ltd Login.js"use strict" var React = require('react'); var controller; var Login = React.createClass({ getInitialState: function() { return { status: 'initial', } }, componentWillMount: function() { controller = require('./Login-controller')(this.props.controller, this); }, render: function() { console.log('rendering Login'); if (this.props.loggedIn) { return ( <div></div> ); } return ( <table id="loginTable"> <tbody> <tr> <td>Username: </td> <td><input id="username" /> </td> </tr> <tr> <td>Password: </td> <td><input id="password" type="password" /> </td> </tr> <tr> <td colSpan="2"> <button id="LoginBtn" onClick={this.LoginBtnClicked} > Login </button> </td> </tr> </tbody> </table> ); } }); module.exports = Login;
  • 30. Copyright © 2016 M/Gateway Developments Ltd Login.js"use strict" var React = require('react'); var controller; var Login = React.createClass({ getInitialState: function() { return { status: 'initial', } }, componentWillMount: function() { controller = require('./Login-controller')(this.props.controller, this); }, render: function() { console.log('rendering Login'); if (this.props.loggedIn) { return ( <div></div> ); } return ( <table id="loginTable"> <tbody> <tr> <td>Username: </td> <td><input id="username" /> </td> </tr> <tr> <td>Password: </td> <td><input id="password" type="password" /> </td> </tr> <tr> <td colSpan="2"> <button id="LoginBtn" onClick={this.LoginBtnClicked} > Login </button> </td> </tr> </tbody> </table> ); } }); module.exports = Login; On successful login, display nothing Form disappears
  • 31. Copyright © 2016 M/Gateway Developments Ltd Login.js"use strict" var React = require('react'); var controller; var Login = React.createClass({ getInitialState: function() { return { status: 'initial', } }, componentWillMount: function() { controller = require('./Login-controller')(this.props.controller, this); }, render: function() { console.log('rendering Login'); if (this.props.loggedIn) { return ( <div></div> ); } return ( <table id="loginTable"> <tbody> <tr> <td>Username: </td> <td><input id="username" /> </td> </tr> <tr> <td>Password: </td> <td><input id="password" type="password" /> </td> </tr> <tr> <td colSpan="2"> <button id="LoginBtn" onClick={this.LoginBtnClicked} > Login </button> </td> </tr> </tbody> </table> ); } }); module.exports = Login; Otherwise, display the form
  • 32. Copyright © 2016 M/Gateway Developments Ltd Login.js"use strict" var React = require('react'); var controller; var Login = React.createClass({ getInitialState: function() { return { status: 'initial', } }, componentWillMount: function() { controller = require('./Login-controller')(this.props.controller, this); }, render: function() { console.log('rendering Login'); if (this.props.loggedIn) { return ( <div></div> ); } return ( <table id="loginTable"> <tbody> <tr> <td>Username: </td> <td><input id="username" /> </td> </tr> <tr> <td>Password: </td> <td><input id="password" type="password" /> </td> </tr> <tr> <td colSpan="2"> <button id="LoginBtn" onClick={this.LoginBtnClicked} > Login </button> </td> </tr> </tbody> </table> ); } }); module.exports = Login; JSX Click handler
  • 33. Copyright © 2016 M/Gateway Developments Ltd Login-controller.js module.exports = function (controller, component) { component.LoginBtnClicked = function(e) { var username = $('#username').val(); var password = $('#password').val(); if (username === '') { alert('You must enter a username!'); return; } if (password === '') { alert('You must enter a password!'); return; } controller.send({ type: 'login', params: { username: username, password: password } }); }; return controller; };
  • 34. Copyright © 2016 M/Gateway Developments Ltd Login-controller.js module.exports = function (controller, component) { component.LoginBtnClicked = function(e) { var username = $('#username').val(); var password = $('#password').val(); if (username === '') { alert('You must enter a username!'); return; } if (password === '') { alert('You must enter a password!'); return; } controller.send({ type: 'login', params: { username: username, password: password } }); }; return controller; }; Define the Login button's click handler
  • 35. Copyright © 2016 M/Gateway Developments Ltd Login-controller.js module.exports = function (controller, component) { component.LoginBtnClicked = function(e) { var username = $('#username').val(); var password = $('#password').val(); if (username === '') { alert('You must enter a username!'); return; } if (password === '') { alert('You must enter a password!'); return; } controller.send({ type: 'login', params: { username: username, password: password } }); }; return controller; }; Send the username and password to the ewd-xpress Back-end The response is handled in the Parent component
  • 36. Copyright © 2016 M/Gateway Developments Ltd Content.js var React = require('react'); var controller; var Content = React.createClass({ componentWillMount: function() { controller = require('./Content-controller')(this.props.controller, this); }, componentWillReceiveProps: function(newProps) { this.updateContent(newProps.content); }, render: function() { console.log('Rendering Content'); return ( <div> {this.content} </div> ); } }); module.exports = Content;
  • 37. Copyright © 2016 M/Gateway Developments Ltd Content.js var React = require('react'); var controller; var Content = React.createClass({ componentWillMount: function() { controller = require('./Content-controller')(this.props.controller, this); }, componentWillReceiveProps: function(newProps) { this.updateContent(newProps.content); }, render: function() { console.log('Rendering Content'); return ( <div> {this.content} </div> ); } }); module.exports = Content; Simply display the value of this.content each Time it renders
  • 38. Copyright © 2016 M/Gateway Developments Ltd Content.js var React = require('react'); var controller; var Content = React.createClass({ componentWillMount: function() { controller = require('./Content-controller')(this.props.controller, this); }, componentWillReceiveProps: function(newProps) { this.updateContent(newProps.content); }, render: function() { console.log('Rendering Content'); return ( <div> {this.content} </div> ); } }); module.exports = Content; Use the componentWillReceiveProps life-cycle method to update the content whenever re-rendering occurs
  • 39. Copyright © 2016 M/Gateway Developments Ltd Content.js var React = require('react'); var controller; var Content = React.createClass({ componentWillMount: function() { controller = require('./Content-controller')(this.props.controller, this); }, componentWillReceiveProps: function(newProps) { this.updateContent(newProps.content); }, render: function() { console.log('Rendering Content'); return ( <div> {this.content} </div> ); } }); module.exports = Content; The componentWillReceiveProps life-cycle method will invoke a method named this.updateContent We'll define it in the content-controller module
  • 40. Copyright © 2016 M/Gateway Developments Ltd Content-controller.js module.exports = function (controller, component) { component.content = component.props.content; component.updateContent = function(newContent) { if (newContent !== '') { component.content = newContent; } }; return controller; };
  • 41. Copyright © 2016 M/Gateway Developments Ltd Content-controller.js module.exports = function (controller, component) { component.content = component.props.content; component.updateContent = function(newContent) { if (newContent !== '') { component.content = newContent; } }; return controller; }; Here's the this.updateContent Method It just updates this.content Within the controller, instead of this we refer to component
  • 42. Copyright © 2016 M/Gateway Developments Ltd Finally the back-end Module • This must handle the login message that is sent from the browser when the Login form button is clicked • It must validate the username and password • For simplicity, we'll just hard-code the valid values – In a real-world app, you'd authenticate against a database or using a dedicated API
  • 43. Copyright © 2016 M/Gateway Developments Ltd Finally the back-end Module • It's advisable to repeat any browser-side validation at the back-end – A malicious user might attempt to send a login message via the JavaScript console • We'll authenticate the user and prevent an already-logged in user from logging in again
  • 44. Copyright © 2016 M/Gateway Developments Ltd Back-end module module.exports = { handlers: { login: function(messageObj, session, send, finished) { if (session.authenticated) { finished({error: 'You have already logged in'}); return; } if (messageObj.params.username === '') { finished({error: 'You must enter a username'}); return; } if (messageObj.params.password === '') { finished({error: 'You must enter a password'}); return; } if (messageObj.params.username !== 'rob') { finished({error: 'Invalid username'}); return; } if (messageObj.params.password !== 'secret') { finished({error: 'Invalid password'}); return; } session.authenticated = true; finished({ ok: true, name: 'Rob' }); } } }; ~/qewd/node_modules/react-demo1.js
  • 45. Copyright © 2016 M/Gateway Developments Ltd Back-end module module.exports = { handlers: { login: function(messageObj, session, send, finished) { if (session.authenticated) { finished({error: 'You have already logged in'}); return; } if (messageObj.params.username === '') { finished({error: 'You must enter a username'}); return; } if (messageObj.params.password === '') { finished({error: 'You must enter a password'}); return; } if (messageObj.params.username !== 'rob') { finished({error: 'Invalid username'}); return; } if (messageObj.params.password !== 'secret') { finished({error: 'Invalid password'}); return; } session.authenticated = true; finished({ ok: true, name: 'Rob' }); } } }; ~/qewd/node_modules/react-demo1.js Repeat the Browser-side Validation Return an error object if it fails
  • 46. Copyright © 2016 M/Gateway Developments Ltd Back-end module module.exports = { handlers: { login: function(messageObj, session, send, finished) { if (session.authenticated) { finished({error: 'You have already logged in'}); return; } if (messageObj.params.username === '') { finished({error: 'You must enter a username'}); return; } if (messageObj.params.password === '') { finished({error: 'You must enter a password'}); return; } if (messageObj.params.username !== 'rob') { finished({error: 'Invalid username'}); return; } if (messageObj.params.password !== 'secret') { finished({error: 'Invalid password'}); return; } session.authenticated = true; finished({ ok: true, name: 'Rob' }); } } }; ~/qewd/node_modules/react-demo1.js Here's our simple hard-coded validation Username must be 'rob' and password must be 'secret'
  • 47. Copyright © 2016 M/Gateway Developments Ltd Back-end module module.exports = { handlers: { login: function(messageObj, session, send, finished) { if (session.authenticated) { finished({error: 'You have already logged in'}); return; } if (messageObj.params.username === '') { finished({error: 'You must enter a username'}); return; } if (messageObj.params.password === '') { finished({error: 'You must enter a password'}); return; } if (messageObj.params.username !== 'rob') { finished({error: 'Invalid username'}); return; } if (messageObj.params.password !== 'secret') { finished({error: 'Invalid password'}); return; } session.authenticated = true; finished({ ok: true, name: 'Rob' }); } } }; ~/qewd/node_modules/react-demo1.js Set the session authenticated property
  • 48. Copyright © 2016 M/Gateway Developments Ltd Back-end module module.exports = { handlers: { login: function(messageObj, session, send, finished) { if (session.authenticated) { finished({error: 'You have already logged in'}); return; } if (messageObj.params.username === '') { finished({error: 'You must enter a username'}); return; } if (messageObj.params.password === '') { finished({error: 'You must enter a password'}); return; } if (messageObj.params.username !== 'rob') { finished({error: 'Invalid username'}); return; } if (messageObj.params.password !== 'secret') { finished({error: 'Invalid password'}); return; } session.authenticated = true; finished({ ok: true, name: 'Rob' }); } } }; ~/qewd/node_modules/react-demo1.js Return a user name in the response object This simple example uses a hard-coded value: 'Rob'
  • 49. Copyright © 2016 M/Gateway Developments Ltd That should be it! • Re-bundle it using Browserify in the normal way • Try running it!
  • 50. Copyright © 2016 M/Gateway Developments Ltd Try it
  • 51. Copyright © 2016 M/Gateway Developments Ltd React.js Design Main Page Title / Banner Login Form Content Initially Initial Title Display the form No Content
  • 52. Copyright © 2016 M/Gateway Developments Ltd Login with wrong credentials
  • 53. Copyright © 2016 M/Gateway Developments Ltd React.js Design Main Page Title / Banner Login Form Content On login error Initial Title Display the form No Content Display Error
  • 54. Copyright © 2016 M/Gateway Developments Ltd Successful login Username: rob ; password: secret
  • 55. Copyright © 2016 M/Gateway Developments Ltd React.js Design Main Page Title / Banner Login Form Content On Successful login Hello {{user}} title Hide the form Display Content
  • 56. Copyright © 2016 M/Gateway Developments Ltd How that happened
  • 57. Copyright © 2016 M/Gateway Developments Ltd React.js Design Main Page Title / Banner Login Form Content React.js Mechanics Send username & password as EWD message
  • 58. Copyright © 2016 M/Gateway Developments Ltd Login-controller.js module.exports = function (controller, component) { component.LoginBtnClicked = function(e) { var username = $('#username').val(); var password = $('#password').val(); if (username === '') { alert('You must enter a username!'); return; } if (password === '') { alert('You must enter a password!'); return; } controller.send({ type: 'login', params: { username: username, password: password } }); }; return controller; }; Define the Login button's click handler
  • 59. Copyright © 2016 M/Gateway Developments Ltd Login-controller.js module.exports = function (controller, component) { component.LoginBtnClicked = function(e) { var username = $('#username').val(); var password = $('#password').val(); if (username === '') { alert('You must enter a username!'); return; } if (password === '') { alert('You must enter a password!'); return; } controller.send({ type: 'login', params: { username: username, password: password } }); }; return controller; }; Send the username and password to the ewd-xpress Back-end The response is handled in the Parent component
  • 60. Copyright © 2016 M/Gateway Developments Ltd React.js Design Main Page Title / Banner Login Form Content React.js Mechanics Send username & password as EWD message To Back-end module: react-demo1.js
  • 61. Copyright © 2016 M/Gateway Developments Ltd Back-end module module.exports = { handlers: { login: function(messageObj, session, send, finished) { if (session.authenticated) { finished({error: 'You have already logged in'}); return; } if (messageObj.params.username === '') { finished({error: 'You must enter a username'}); return; } if (messageObj.params.password === '') { finished({error: 'You must enter a password'}); return; } if (messageObj.params.username !== 'rob') { finished({error: 'Invalid username'}); return; } if (messageObj.params.password !== 'secret') { finished({error: 'Invalid password'}); return; } session.authenticated = true; finished({ ok: true, name: 'Rob' }); } } }; ~/qewd/node_modules/react-demo1.js Here's our simple hard-coded validation Username must be 'rob' and password must be 'secret'
  • 62. Copyright © 2016 M/Gateway Developments Ltd React.js Design Main Page Title / Banner Login Form Content React.js Mechanics From Back-end Handle response
  • 63. Copyright © 2016 M/Gateway Developments Ltd MainPage-controller.js module.exports = function (controller, component) { controller.log = true; component.loggedIn = false; component.username = ''; component.content = ''; controller.on('error', function(responseObj) { alert('Error: ' + responseObj.message.error); }); controller.on('login', function(responseObj) { if (!responseObj.message.error) { console.log('Logged in!'); component.loggedIn = true; component.username = responseObj.message.name; component.content = 'User has logged in - ready to display some content for the user!'; component.setState({ status: 'loggedIn' }); } }); return controller; }; error handler displays alerts
  • 64. Copyright © 2016 M/Gateway Developments Ltd React.js Design Main Page Title / Banner Login Form Content React.js Mechanics Error response received: Display Error
  • 65. Copyright © 2016 M/Gateway Developments Ltd MainPage-controller.js module.exports = function (controller, component) { controller.log = true; component.loggedIn = false; component.username = ''; component.content = ''; controller.on('error', function(responseObj) { alert('Error: ' + responseObj.message.error); }); controller.on('login', function(responseObj) { if (!responseObj.message.error) { console.log('Logged in!'); component.loggedIn = true; component.username = responseObj.message.name; component.content = 'User has logged in - ready to display some content for the user!'; component.setState({ status: 'loggedIn' }); } }); return controller; }; login handler deals with successful logins
  • 66. Copyright © 2016 M/Gateway Developments Ltd MainPage-controller.js module.exports = function (controller, component) { controller.log = true; component.loggedIn = false; component.username = ''; component.content = ''; controller.on('error', function(responseObj) { alert('Error: ' + responseObj.message.error); }); controller.on('login', function(responseObj) { if (!responseObj.message.error) { console.log('Logged in!'); component.loggedIn = true; component.username = responseObj.message.name; component.content = 'User has logged in - ready to display some content for the user!'; component.setState({ status: 'loggedIn' }); } }); return controller; }; New values passed as props to child components if login is successful
  • 67. Copyright © 2016 M/Gateway Developments Ltd MainPage-controller.js module.exports = function (controller, component) { controller.log = true; component.loggedIn = false; component.username = ''; component.content = ''; controller.on('error', function(responseObj) { alert('Error: ' + responseObj.message.error); }); controller.on('login', function(responseObj) { if (!responseObj.message.error) { console.log('Logged in!'); component.loggedIn = true; component.username = responseObj.message.name; component.content = 'User has logged in - ready to display some content for the user!'; component.setState({ status: 'loggedIn' }); } }); return controller; }; State value changed to trigger re-render of this component and its child components
  • 68. Copyright © 2016 M/Gateway Developments Ltd React.js Design Main Page Title / Banner Login Form Content React.js Mechanics Success response received: Re-render
  • 69. Copyright © 2016 M/Gateway Developments Ltd MainPage.js "use strict" var React = require('react'); var Title = require('./Title'); var Content = require('./Content'); var Login = require('./Login'); var jQuery = require('jquery'); window.$ = window.jQuery = jQuery; var controller; var MainPage = React.createClass({ getInitialState: function() { return { status: 'initial', } }, componentWillMount: function() { controller = require('./MainPage-controller')(this.props.controller, this); }, render: function() { console.log('Rendering MainPage'); return ( <div> <Title controller = {controller} username = {this.username} /> <Login controller = {controller} loggedIn = {this.loggedIn} /> <Content controller = {controller} content = {this.content} /> </div> ); } }); module.exports = MainPage; props passed to child components
  • 70. Copyright © 2016 M/Gateway Developments Ltd React.js Design Main Page Title / Banner Login Form Content React.js Mechanics Pass down Username as prop
  • 71. Copyright © 2016 M/Gateway Developments Ltd React.js Design Main Page Title / Banner Login Form Content React.js Mechanics Pass prop to Signal successful login
  • 72. Copyright © 2016 M/Gateway Developments Ltd React.js Design Main Page Title / Banner Login Form Content React.js Mechanics Pass prop to signal that content should be displayed
  • 73. Copyright © 2016 M/Gateway Developments Ltd And so we have a working demo! Username: rob ; password: secret