SlideShare a Scribd company logo
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

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...
Rob Tweed
 
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
Rob Tweed
 
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...
Rob Tweed
 
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
Rob Tweed
 
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
Rob Tweed
 
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
Rob Tweed
 
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
Rob Tweed
 
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
Rob Tweed
 
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
Rob Tweed
 
Micronaut For Single Page Apps
Micronaut For Single Page AppsMicronaut For Single Page Apps
Micronaut For Single Page Apps
Zachary Klein
 
React js
React jsReact js
Angular beans
Angular beansAngular beans
Angular beans
Bessem Hmidi
 
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
Rob Tweed
 
Dsc Charusat Learning React Part 1
Dsc Charusat Learning React Part 1 Dsc Charusat Learning React Part 1
Dsc Charusat Learning React Part 1
JainamMehta19
 
Getting Started with React v16
Getting Started with React v16Getting Started with React v16
Getting Started with React v16
Benny Neugebauer
 
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
Mek Srunyu Stittri
 
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
Edureka!
 
Serverless Java on Kubernetes
Serverless Java on KubernetesServerless Java on Kubernetes
Serverless Java on Kubernetes
Krzysztof Sobkowiak
 
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
Mek Srunyu Stittri
 
Intro to ReactJS
Intro to ReactJSIntro to ReactJS
Intro to ReactJS
Harvard Web Working Group
 

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

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
Rob Tweed
 
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
Rob Tweed
 
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
Rob Tweed
 
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
Rob Tweed
 
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
Rob Tweed
 
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
Rob Tweed
 
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
Rob Tweed
 
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
Rob Tweed
 
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...
Rob Tweed
 
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
Rob Tweed
 
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
Rob Tweed
 
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
Rob Tweed
 
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”...
Ontico
 
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
Rob Tweed
 
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
Rob Tweed
 
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
Rob Tweed
 
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
Rob Tweed
 

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

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
epamspb
 
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
Katy Slemon
 
Introduction to React for Frontend Developers
Introduction to React for Frontend DevelopersIntroduction to React for Frontend Developers
Introduction to React for Frontend Developers
Sergio Nakamura
 
React outbox
React outboxReact outbox
React outbox
Angela Lehru
 
React & Redux for noobs
React & Redux for noobsReact & Redux for noobs
React & Redux for noobs
[T]echdencias
 
JSLab. Алексей Волков. "React на практике"
JSLab. Алексей Волков. "React на практике"JSLab. Алексей Волков. "React на практике"
JSLab. Алексей Волков. "React на практике"
GeeksLab Odessa
 
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
Max Pronko
 
Intro react js
Intro react jsIntro react js
Intro react js
Vijayakanth MP
 
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
Ignacio Martín
 
Advanced SharePoint Web Part Development
Advanced SharePoint Web Part DevelopmentAdvanced SharePoint Web Part Development
Advanced SharePoint Web Part Development
Rob Windsor
 
Hybrid App using WordPress
Hybrid App using WordPressHybrid App using WordPress
Hybrid App using WordPress
Haim Michael
 
Web Components for Java Developers
Web Components for Java DevelopersWeb Components for Java Developers
Web Components for Java Developers
Joonas Lehtinen
 
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)
MichaelBontyes
 
Apache Aries Blog Sample
Apache Aries Blog SampleApache Aries Blog Sample
Apache Aries Blog Sample
Skills Matter
 
The WebView Role in Hybrid Applications
The WebView Role in Hybrid ApplicationsThe WebView Role in Hybrid Applications
The WebView Role in Hybrid Applications
Haim Michael
 
Avinash Kundaliya: Javascript and WordPress
Avinash Kundaliya: Javascript and WordPressAvinash Kundaliya: Javascript and WordPress
Avinash Kundaliya: Javascript and WordPress
wpnepal
 
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
Riad Benguella
 
Rails is not just Ruby
Rails is not just RubyRails is not just Ruby
Rails is not just Ruby
Marco Otte-Witte
 
Academy PRO: React JS
Academy PRO: React JSAcademy PRO: React JS
Academy PRO: React JS
Binary Studio
 
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
Binary Studio
 

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

QEWD Update
QEWD UpdateQEWD Update
QEWD Update
Rob Tweed
 
Data Persistence as a Language Feature
Data Persistence as a Language FeatureData Persistence as a Language Feature
Data Persistence as a Language Feature
Rob Tweed
 
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
Rob Tweed
 
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
Rob Tweed
 
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
Rob Tweed
 
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
Rob Tweed
 
QEWD.js, JSON Web Tokens & MicroServices
QEWD.js, JSON Web Tokens & MicroServicesQEWD.js, JSON Web Tokens & MicroServices
QEWD.js, JSON Web Tokens & MicroServices
Rob Tweed
 
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
Rob Tweed
 
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
Rob Tweed
 
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
Rob Tweed
 
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
Rob Tweed
 
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
Rob Tweed
 
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
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

Maximizing Efficiency and Profitability: Optimizing Data Systems, Enhancing C...
Maximizing Efficiency and Profitability: Optimizing Data Systems, Enhancing C...Maximizing Efficiency and Profitability: Optimizing Data Systems, Enhancing C...
Maximizing Efficiency and Profitability: Optimizing Data Systems, Enhancing C...
OnePlan Solutions
 
How To Fill Timesheet in TaskSprint: Quick Guide 2024
How To Fill Timesheet in TaskSprint: Quick Guide 2024How To Fill Timesheet in TaskSprint: Quick Guide 2024
How To Fill Timesheet in TaskSprint: Quick Guide 2024
TaskSprint | Employee Efficiency Software
 
Odoo E-commerce website development guides
Odoo E-commerce website development guidesOdoo E-commerce website development guides
Odoo E-commerce website development guides
jhkdigitalmarketing
 
Introduction to Cloud computing for Internet of Things
Introduction to Cloud computing for Internet of ThingsIntroduction to Cloud computing for Internet of Things
Introduction to Cloud computing for Internet of Things
NachuSubramanian1
 
Mobile App Development Company in Noida - Drona Infotech.
Mobile App Development Company in Noida - Drona Infotech.Mobile App Development Company in Noida - Drona Infotech.
Mobile App Development Company in Noida - Drona Infotech.
Mobile App Development Company in Noida - Drona Infotech
 
A Step-by-Step Guide to Selecting the Right Automated Software Testing Tools.pdf
A Step-by-Step Guide to Selecting the Right Automated Software Testing Tools.pdfA Step-by-Step Guide to Selecting the Right Automated Software Testing Tools.pdf
A Step-by-Step Guide to Selecting the Right Automated Software Testing Tools.pdf
kalichargn70th171
 
Celebrity Girls Call Mumbai 🛵🚡9910780858 💃 Choose Best And Top Girl Service A...
Celebrity Girls Call Mumbai 🛵🚡9910780858 💃 Choose Best And Top Girl Service A...Celebrity Girls Call Mumbai 🛵🚡9910780858 💃 Choose Best And Top Girl Service A...
Celebrity Girls Call Mumbai 🛵🚡9910780858 💃 Choose Best And Top Girl Service A...
norina2645
 
Vip Girls Call ServiCe Hyderabad 0000000000 Pooja Best High Class Hyderabad A...
Vip Girls Call ServiCe Hyderabad 0000000000 Pooja Best High Class Hyderabad A...Vip Girls Call ServiCe Hyderabad 0000000000 Pooja Best High Class Hyderabad A...
Vip Girls Call ServiCe Hyderabad 0000000000 Pooja Best High Class Hyderabad A...
ashiklo9823
 
Girls Call Mysore 000XX00000 Provide Best And Top Girl Service And No1 in City
Girls Call Mysore 000XX00000 Provide Best And Top Girl Service And No1 in CityGirls Call Mysore 000XX00000 Provide Best And Top Girl Service And No1 in City
Girls Call Mysore 000XX00000 Provide Best And Top Girl Service And No1 in City
neshakor5152
 
🚂🚘 Premium Girls Call Ranchi 🛵🚡000XX00000 💃 Choose Best And Top Girl Service...
🚂🚘 Premium Girls Call Ranchi  🛵🚡000XX00000 💃 Choose Best And Top Girl Service...🚂🚘 Premium Girls Call Ranchi  🛵🚡000XX00000 💃 Choose Best And Top Girl Service...
🚂🚘 Premium Girls Call Ranchi 🛵🚡000XX00000 💃 Choose Best And Top Girl Service...
bahubalikumar09988
 
High Girls Call Chennai 000XX00000 Provide Best And Top Girl Service And No1 ...
High Girls Call Chennai 000XX00000 Provide Best And Top Girl Service And No1 ...High Girls Call Chennai 000XX00000 Provide Best And Top Girl Service And No1 ...
High Girls Call Chennai 000XX00000 Provide Best And Top Girl Service And No1 ...
singhlata50dh
 
Celebrity Girls Call Mumbai 9930687706 Unlimited Short Providing Girls Servic...
Celebrity Girls Call Mumbai 9930687706 Unlimited Short Providing Girls Servic...Celebrity Girls Call Mumbai 9930687706 Unlimited Short Providing Girls Servic...
Celebrity Girls Call Mumbai 9930687706 Unlimited Short Providing Girls Servic...
kiara pandey
 
Unleashing the Future: Building a Scalable and Up-to-Date GenAI Chatbot with ...
Unleashing the Future: Building a Scalable and Up-to-Date GenAI Chatbot with ...Unleashing the Future: Building a Scalable and Up-to-Date GenAI Chatbot with ...
Unleashing the Future: Building a Scalable and Up-to-Date GenAI Chatbot with ...
confluent
 
welcome to presentation on Google Apps
welcome to   presentation on Google Appswelcome to   presentation on Google Apps
welcome to presentation on Google Apps
AsifKarimJim
 
Agra Girls Call Agra 0X0000000X Unlimited Short Providing Girls Service Avail...
Agra Girls Call Agra 0X0000000X Unlimited Short Providing Girls Service Avail...Agra Girls Call Agra 0X0000000X Unlimited Short Providing Girls Service Avail...
Agra Girls Call Agra 0X0000000X Unlimited Short Providing Girls Service Avail...
rachitkumar09887
 
Wired_2.0_Create_AmsterdamJUG_09072024.pptx
Wired_2.0_Create_AmsterdamJUG_09072024.pptxWired_2.0_Create_AmsterdamJUG_09072024.pptx
Wired_2.0_Create_AmsterdamJUG_09072024.pptx
SimonedeGijt
 
Verified Girls Call Mumbai 👀 9820252231 👀 Cash Payment With Room DeliveryDeli...
Verified Girls Call Mumbai 👀 9820252231 👀 Cash Payment With Room DeliveryDeli...Verified Girls Call Mumbai 👀 9820252231 👀 Cash Payment With Room DeliveryDeli...
Verified Girls Call Mumbai 👀 9820252231 👀 Cash Payment With Room DeliveryDeli...
87tomato
 
IoT In Manufacturing_ Use Cases, Benefits, and Challenges.pdf
IoT In Manufacturing_ Use Cases, Benefits, and Challenges.pdfIoT In Manufacturing_ Use Cases, Benefits, and Challenges.pdf
IoT In Manufacturing_ Use Cases, Benefits, and Challenges.pdf
mohitd6
 
Russian Girls Call Mumbai 🎈🔥9930687706 🔥💋🎈 Provide Best And Top Girl Service ...
Russian Girls Call Mumbai 🎈🔥9930687706 🔥💋🎈 Provide Best And Top Girl Service ...Russian Girls Call Mumbai 🎈🔥9930687706 🔥💋🎈 Provide Best And Top Girl Service ...
Russian Girls Call Mumbai 🎈🔥9930687706 🔥💋🎈 Provide Best And Top Girl Service ...
shanihomely
 
To Avoid Mistakes When Using Online Attendance Sheets
To Avoid Mistakes When Using Online Attendance SheetsTo Avoid Mistakes When Using Online Attendance Sheets
To Avoid Mistakes When Using Online Attendance Sheets
Task Tracker
 

Recently uploaded (20)

Maximizing Efficiency and Profitability: Optimizing Data Systems, Enhancing C...
Maximizing Efficiency and Profitability: Optimizing Data Systems, Enhancing C...Maximizing Efficiency and Profitability: Optimizing Data Systems, Enhancing C...
Maximizing Efficiency and Profitability: Optimizing Data Systems, Enhancing C...
 
How To Fill Timesheet in TaskSprint: Quick Guide 2024
How To Fill Timesheet in TaskSprint: Quick Guide 2024How To Fill Timesheet in TaskSprint: Quick Guide 2024
How To Fill Timesheet in TaskSprint: Quick Guide 2024
 
Odoo E-commerce website development guides
Odoo E-commerce website development guidesOdoo E-commerce website development guides
Odoo E-commerce website development guides
 
Introduction to Cloud computing for Internet of Things
Introduction to Cloud computing for Internet of ThingsIntroduction to Cloud computing for Internet of Things
Introduction to Cloud computing for Internet of Things
 
Mobile App Development Company in Noida - Drona Infotech.
Mobile App Development Company in Noida - Drona Infotech.Mobile App Development Company in Noida - Drona Infotech.
Mobile App Development Company in Noida - Drona Infotech.
 
A Step-by-Step Guide to Selecting the Right Automated Software Testing Tools.pdf
A Step-by-Step Guide to Selecting the Right Automated Software Testing Tools.pdfA Step-by-Step Guide to Selecting the Right Automated Software Testing Tools.pdf
A Step-by-Step Guide to Selecting the Right Automated Software Testing Tools.pdf
 
Celebrity Girls Call Mumbai 🛵🚡9910780858 💃 Choose Best And Top Girl Service A...
Celebrity Girls Call Mumbai 🛵🚡9910780858 💃 Choose Best And Top Girl Service A...Celebrity Girls Call Mumbai 🛵🚡9910780858 💃 Choose Best And Top Girl Service A...
Celebrity Girls Call Mumbai 🛵🚡9910780858 💃 Choose Best And Top Girl Service A...
 
Vip Girls Call ServiCe Hyderabad 0000000000 Pooja Best High Class Hyderabad A...
Vip Girls Call ServiCe Hyderabad 0000000000 Pooja Best High Class Hyderabad A...Vip Girls Call ServiCe Hyderabad 0000000000 Pooja Best High Class Hyderabad A...
Vip Girls Call ServiCe Hyderabad 0000000000 Pooja Best High Class Hyderabad A...
 
Girls Call Mysore 000XX00000 Provide Best And Top Girl Service And No1 in City
Girls Call Mysore 000XX00000 Provide Best And Top Girl Service And No1 in CityGirls Call Mysore 000XX00000 Provide Best And Top Girl Service And No1 in City
Girls Call Mysore 000XX00000 Provide Best And Top Girl Service And No1 in City
 
🚂🚘 Premium Girls Call Ranchi 🛵🚡000XX00000 💃 Choose Best And Top Girl Service...
🚂🚘 Premium Girls Call Ranchi  🛵🚡000XX00000 💃 Choose Best And Top Girl Service...🚂🚘 Premium Girls Call Ranchi  🛵🚡000XX00000 💃 Choose Best And Top Girl Service...
🚂🚘 Premium Girls Call Ranchi 🛵🚡000XX00000 💃 Choose Best And Top Girl Service...
 
High Girls Call Chennai 000XX00000 Provide Best And Top Girl Service And No1 ...
High Girls Call Chennai 000XX00000 Provide Best And Top Girl Service And No1 ...High Girls Call Chennai 000XX00000 Provide Best And Top Girl Service And No1 ...
High Girls Call Chennai 000XX00000 Provide Best And Top Girl Service And No1 ...
 
Celebrity Girls Call Mumbai 9930687706 Unlimited Short Providing Girls Servic...
Celebrity Girls Call Mumbai 9930687706 Unlimited Short Providing Girls Servic...Celebrity Girls Call Mumbai 9930687706 Unlimited Short Providing Girls Servic...
Celebrity Girls Call Mumbai 9930687706 Unlimited Short Providing Girls Servic...
 
Unleashing the Future: Building a Scalable and Up-to-Date GenAI Chatbot with ...
Unleashing the Future: Building a Scalable and Up-to-Date GenAI Chatbot with ...Unleashing the Future: Building a Scalable and Up-to-Date GenAI Chatbot with ...
Unleashing the Future: Building a Scalable and Up-to-Date GenAI Chatbot with ...
 
welcome to presentation on Google Apps
welcome to   presentation on Google Appswelcome to   presentation on Google Apps
welcome to presentation on Google Apps
 
Agra Girls Call Agra 0X0000000X Unlimited Short Providing Girls Service Avail...
Agra Girls Call Agra 0X0000000X Unlimited Short Providing Girls Service Avail...Agra Girls Call Agra 0X0000000X Unlimited Short Providing Girls Service Avail...
Agra Girls Call Agra 0X0000000X Unlimited Short Providing Girls Service Avail...
 
Wired_2.0_Create_AmsterdamJUG_09072024.pptx
Wired_2.0_Create_AmsterdamJUG_09072024.pptxWired_2.0_Create_AmsterdamJUG_09072024.pptx
Wired_2.0_Create_AmsterdamJUG_09072024.pptx
 
Verified Girls Call Mumbai 👀 9820252231 👀 Cash Payment With Room DeliveryDeli...
Verified Girls Call Mumbai 👀 9820252231 👀 Cash Payment With Room DeliveryDeli...Verified Girls Call Mumbai 👀 9820252231 👀 Cash Payment With Room DeliveryDeli...
Verified Girls Call Mumbai 👀 9820252231 👀 Cash Payment With Room DeliveryDeli...
 
IoT In Manufacturing_ Use Cases, Benefits, and Challenges.pdf
IoT In Manufacturing_ Use Cases, Benefits, and Challenges.pdfIoT In Manufacturing_ Use Cases, Benefits, and Challenges.pdf
IoT In Manufacturing_ Use Cases, Benefits, and Challenges.pdf
 
Russian Girls Call Mumbai 🎈🔥9930687706 🔥💋🎈 Provide Best And Top Girl Service ...
Russian Girls Call Mumbai 🎈🔥9930687706 🔥💋🎈 Provide Best And Top Girl Service ...Russian Girls Call Mumbai 🎈🔥9930687706 🔥💋🎈 Provide Best And Top Girl Service ...
Russian Girls Call Mumbai 🎈🔥9930687706 🔥💋🎈 Provide Best And Top Girl Service ...
 
To Avoid Mistakes When Using Online Attendance Sheets
To Avoid Mistakes When Using Online Attendance SheetsTo Avoid Mistakes When Using Online Attendance Sheets
To Avoid Mistakes When Using Online Attendance Sheets
 

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