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

73
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

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

Copyright © 2016 M/Gateway Developments Ltd

EWD 3 Training CoursePart 41

Building a React.js-based QEWD Application

(e) Building out a login sequence

Rob TweedDirector, 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 Successfullogin

Hello {{user}}title

Hide the form DisplayContent

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

messageTo QEWDBack-end

Copyright © 2016 M/Gateway Developments Ltd

React.js Design

Main Page

Title / Banner Login Form Content

React.js Mechanics

FromBack-end

Handle response

Copyright © 2016 M/Gateway Developments Ltd

React.js Design

Main Page

Title / Banner Login Form Content

React.js Mechanics

Error responsereceived:

Display Error

Copyright © 2016 M/Gateway Developments Ltd

React.js Design

Main Page

Title / Banner Login Form Content

React.js Mechanics

Success responsereceived:

Re-render

Copyright © 2016 M/Gateway Developments Ltd

React.js Design

Main Page

Title / Banner Login Form Content

React.js Mechanics

Pass downUsername as

prop

Copyright © 2016 M/Gateway Developments Ltd

React.js Design

Main Page

Title / Banner Login Form Content

React.js Mechanics

Pass prop toSignal successful

login

Copyright © 2016 M/Gateway Developments Ltd

React.js Design

Main Page

Title / Banner Login Form Content

React.js Mechanics

Pass prop tosignal that

content shouldbe 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 statevariable 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 passedto child

components

Copyright © 2016 M/Gateway Developments Ltd

MainPage-controller.jsmodule.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.jsmodule.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;};

Responsefrom back-endhandled in thistop component

Copyright © 2016 M/Gateway Developments Ltd

MainPage-controller.jsmodule.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 valuespassed as

props to childcomponents

Copyright © 2016 M/Gateway Developments Ltd

MainPage-controller.jsmodule.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 valuespassed as

props to childcomponents

if login issuccessful

Copyright © 2016 M/Gateway Developments Ltd

MainPage-controller.jsmodule.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 valuechanged to

triggerre-render of

this componentand its childcomponents

Copyright © 2016 M/Gateway Developments Ltd

Title.jsvar 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.jsvar 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 propshave changed

Does not fireon initial render

Copyright © 2016 M/Gateway Developments Ltd

Title-controller.jsmodule.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 successfullogin, 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.jsmodule.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.jsmodule.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 theLogin button'sclick handler

Copyright © 2016 M/Gateway Developments Ltd

Login-controller.jsmodule.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 usernameand password tothe ewd-xpress

Back-end

The response ishandled in the

Parent component

Copyright © 2016 M/Gateway Developments Ltd

Content.jsvar 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.jsvar 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 displaythe value of

this.content eachTime it renders

Copyright © 2016 M/Gateway Developments Ltd

Content.jsvar 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 thecomponentWillReceiveProps

life-cycle method toupdate the content

whenever re-renderingoccurs

Copyright © 2016 M/Gateway Developments Ltd

Content.jsvar 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;

ThecomponentWillReceiveProps

life-cycle method willinvoke a method named

this.updateContent

We'll define it in thecontent-controller module

Copyright © 2016 M/Gateway Developments Ltd

Content-controller.jsmodule.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.jsmodule.exports = function (controller, component) {

component.content = component.props.content;

component.updateContent = function(newContent) {if (newContent !== '') {component.content = newContent;

}};

return controller;};

Here's thethis.updateContent

Method

It just updatesthis.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 modulemodule.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 modulemodule.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 theBrowser-side

Validation

Return an errorobject if it fails

Copyright © 2016 M/Gateway Developments Ltd

Back-end modulemodule.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 simplehard-coded validation

Username must be'rob' and password

must be 'secret'

Copyright © 2016 M/Gateway Developments Ltd

Back-end modulemodule.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 sessionauthenticated

property

Copyright © 2016 M/Gateway Developments Ltd

Back-end modulemodule.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 namein the response object

This simple example usesa 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 loginUsername: rob ; password: secret

Copyright © 2016 M/Gateway Developments Ltd

React.js Design

Main Page

Title / Banner Login Form Content

On Successfullogin

Hello {{user}}title

Hide the form DisplayContent

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.jsmodule.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 theLogin button'sclick handler

Copyright © 2016 M/Gateway Developments Ltd

Login-controller.jsmodule.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 usernameand password tothe ewd-xpress

Back-end

The response ishandled 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-endmodule:

react-demo1.js

Copyright © 2016 M/Gateway Developments Ltd

Back-end modulemodule.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 simplehard-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

FromBack-end

Handle response

Copyright © 2016 M/Gateway Developments Ltd

MainPage-controller.jsmodule.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 displaysalerts

Copyright © 2016 M/Gateway Developments Ltd

React.js Design

Main Page

Title / Banner Login Form Content

React.js Mechanics

Error responsereceived:

Display Error

Copyright © 2016 M/Gateway Developments Ltd

MainPage-controller.jsmodule.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 dealswith successful

logins

Copyright © 2016 M/Gateway Developments Ltd

MainPage-controller.jsmodule.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 valuespassed as

props to childcomponents

if login issuccessful

Copyright © 2016 M/Gateway Developments Ltd

MainPage-controller.jsmodule.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 valuechanged to

triggerre-render of

this componentand its childcomponents

Copyright © 2016 M/Gateway Developments Ltd

React.js Design

Main Page

Title / Banner Login Form Content

React.js Mechanics

Success responsereceived:

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 passedto child

components

Copyright © 2016 M/Gateway Developments Ltd

React.js Design

Main Page

Title / Banner Login Form Content

React.js Mechanics

Pass downUsername as

prop

Copyright © 2016 M/Gateway Developments Ltd

React.js Design

Main Page

Title / Banner Login Form Content

React.js Mechanics

Pass prop toSignal successful

login

Copyright © 2016 M/Gateway Developments Ltd

React.js Design

Main Page

Title / Banner Login Form Content

React.js Mechanics

Pass prop tosignal that

content shouldbe displayed

Copyright © 2016 M/Gateway Developments Ltd

And so we have a working demo!Username: rob ; password: secret