A module can add UI to screen/page via layout mechanism, it works like event.
Customize Point
In a component, we should use layout to allow other module can add UI
For example: We use layout for Login component
import SharingAccountPopup from "./SharingAccountPopup"; import layout from "../../../framework/Layout" export class Login extends CoreComponent { static className = 'Login'; template() { return ( <Fragment> <form className="wrapper-login" onSubmit={e => e.preventDefault()}> <div className="form-login"> <strong className="logo"> <a href=""><img src={this.state.logoUrl} alt=""/></a> </strong> /* Use layout to add customize point */ {layout('user')('login_title_before')()(this)} <h2 className="page-title">{this.props.t('Login')}</h2> <div className="form-group group-username"> <label><span> {this.props.t('Username')}</span></label> <input id="username" name="username" type="text" className="form-control" placeholder={this.props.t('Username')} ref="username" onChange={() => this.checkActiveLogin()} onKeyPress={(e) => this.handleUserKeyPress(e)} autoCapitalize="none" /> </div> <div className="form-group group-password"> <label><span>{this.props.t('Password')}</span></label> <input id="password" name="password" type="password" className="form-control" placeholder={this.props.t('Password')} ref="password" onChange={() => this.checkActiveLogin()} onClick={() => this.resetPassword()} onBlur={() => this.checkResetPassword()} onKeyPress={(e) => this.handlePasswordKeyPress(e)} autoComplete="off" /> </div> <div className="form-group"> {loginButton} </div> </div> </form> </Fragment> ); } }
Command layout('user')('login_title_before')()(this)
layout('user')
: Return a layout function foruser
layout('user')('login_title_before')
: Return a layout function foruser.login_title_before
. It equals tolayout('user.login_title_before')
layout('user')('login_title_before')()
: Return a function config of layout, it will receive config from plugin (module)layout('user')('login_title_before')()(this)
: Call layout plugin with param (this)
Plugin to add customize
In the module, we register a layout customize in file etc/config.js
.
For example: We register a layout customize for Login
import ModuleConfigAbstract from "../../ModuleConfigAbstract"; class HelloWorldConfig extends ModuleConfigAbstract{ module = ['helloworld']; layout = { user: { login_title_before: [ 'STATUS: ', function(component) { return component.state.active ? 'Active' : 'Inactive' }, ] } }; } export default (new HelloWorldConfig());
As above, layout plugin functions will be called with param (this). layout('user')('login_title_before')()(this)
will return value of
[ 'STATUS: ', function(component) { return component.state.active ? 'Active' : 'Inactive' }, ]
that each function is called with param (this), then the result may be
[ 'STATUS: ', 'Active', ]
That means, layout plugin can be plain component or a function
For more case, please view files src/framework/Layout.js
and src/framework/__tests__/Layout-test.js
Exercise: Thêm 1 dòng total vào trong total của order detail , có nội dung là Total Added: 0