Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add SilverStripeComponent base class
- Loading branch information
1 parent
bd33696
commit 55085c2
Showing
6 changed files
with
217 additions
and
10 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
# ReactJS Common | ||
|
||
ReactJS Common exposes the required libraries and classes for building React components in SilverStripe CMS. | ||
|
||
## Contents | ||
|
||
- [SilverStripeComponent](silverstripe-component.md): The base class for SilverStripe React components. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,136 @@ | ||
# SilverStripeComponent | ||
|
||
The base class for SilverStripe React components. If you're building React components for the CMS, this is the class you want to extend. `SilverStripeComponent` extends `React.Component` and adds some handy CMS specific behaviour. | ||
|
||
## Creating a component | ||
|
||
__my-component.js__ | ||
```javascript | ||
import SilverStripeComponent from 'silverstripe-component'; | ||
|
||
class MyComponent extends SilverStripeComponent { | ||
|
||
} | ||
|
||
export default MyComponent; | ||
``` | ||
|
||
And that's how you create a SilverStripe React component! | ||
|
||
## Interfacing with ye olde CMS JavaScript | ||
|
||
One of the great things about ReactJS is that it works great with DOM based libraries like jQuery and Entwine. To allow legacy-land script to notify your component about changes add the following to your component. | ||
|
||
__my-component.js__ | ||
```javascript | ||
import SilverStripeComponent from 'silverstripe-component'; | ||
|
||
class MyComponent extends SilverStripeComponent { | ||
componentDidMount() { | ||
super.componentDidMount(); | ||
} | ||
|
||
componentWillUnmount() { | ||
super.componentWillUnmount(); | ||
} | ||
} | ||
|
||
export default MyComponent; | ||
``` | ||
|
||
This is functionally no different from the first example. But it's a good idea to be explicit and add these `super` calls now. You will inevitably add `componentDidMount` and `componentWillUnmount` hooks to your component and it's easy to forget to call `super` then. | ||
|
||
So what's going on when we call those? Glad you asked. If you've passed `cmsEvents` and `cmsEventsNamespace` into your component's `props` then wonderful things will happen. | ||
|
||
Let's take a look at some examples. | ||
|
||
### Getting data into a component | ||
|
||
Sometimes you'll want to call component methods based on events happening outside of your component. For example when a CMS button is clicked you want to highlight your component. | ||
|
||
__main.js__ | ||
```javascript | ||
import $ from 'jquery'; | ||
import React from 'react'; | ||
import MyComponent from './my-component'; | ||
|
||
$('.my-component-wrapper').entwine({ | ||
onadd: function () { | ||
var props = { | ||
cmsEventsNamespace: 'my-component', | ||
cmsEvents: { | ||
highlightComponent: function () { | ||
this.setState({ highlight: true }); | ||
} | ||
} | ||
}; | ||
|
||
React.render( | ||
<MyComponent {...props} />, | ||
this[0] | ||
); | ||
} | ||
}); | ||
``` | ||
|
||
__legacy.js__ | ||
```javascript | ||
(function ($) { | ||
$.entwine('ss', function ($) { | ||
$('.cms-button').entwine({ | ||
onclick: function () { | ||
$(document).trigger('my-component.highlightComponent'); | ||
} | ||
}); | ||
} | ||
}(jQuery)); | ||
``` | ||
Each key in `props.cmsEvents` gets turned into an event listener in `SilverStripeComponent.componentDidMount`. When that namespaced event is triggered on `document` in legacy-land, the associated callback is invoked, in your component. Each callback has the component's context bound so you can set state easily. | ||
All `SilverStripeComponent.componentWillUnmount` does is remove the event listeners. | ||
### Getting data out of a component | ||
There are time you'll want to update legacy-land based on changes in your component too. | ||
`SilverStripeComponent` has a handly method to help with this. | ||
__my-component.js__ | ||
```javascript | ||
import SilverStripeComponent from 'silverstripe-component'; | ||
|
||
class MyComponent extends SilverStripeComponent { | ||
componentDidMount() { | ||
super.componentDidMount(); | ||
} | ||
|
||
componentWillUnmount() { | ||
super.componentWillUnmount(); | ||
} | ||
|
||
componentDidUpdate() { | ||
this._emitCmsEvent('updateCmsHeading', { heading: this.state.headingName }); | ||
} | ||
} | ||
|
||
export default MyComponent; | ||
``` | ||
__legacy.js__ | ||
```javascript | ||
(function ($) { | ||
$.entwine('ss', function ($) { | ||
$('.cms-button').entwine({ | ||
onmatch: function () { | ||
$(document).on('my-component.updateCmsHeading', function (e, data) { | ||
$('.cms-heading').text(data.heading); | ||
}); | ||
}, | ||
onunmatch: function () { | ||
$(document).off('my-component.updateCmsHeading'); | ||
} | ||
}); | ||
} | ||
}(jQuery)); | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
/** | ||
* @file Base component which all SilverStripe ReactJS components should extend from. | ||
*/ | ||
|
||
import React from 'react'; | ||
import $ from 'jquery'; | ||
|
||
class SilverStripeComponent extends React.Component { | ||
|
||
/** | ||
* @func componentDidMount | ||
* @desc Add event listeners which are triggered by the outside (non-react) world. | ||
* This lets us update the component when something happens in legacy JavaScript land. | ||
*/ | ||
componentDidMount() { | ||
if (typeof this.props.cmsEvents === 'undefined' || | ||
typeof this.props.cmsEventsNamespace === 'undefined') { | ||
return; | ||
} | ||
|
||
// Save some props for later. When we come to unbind these listeners | ||
// there's no guarantee these props will be the same or even present. | ||
this.cmsEvents = this.props.cmsEvents; | ||
this.cmsEventsNamespace = this.props.cmsEventsNamespace; | ||
|
||
for (let eventName in this.cmsEvents) { | ||
$(document).on(this.cmsEventsNamespace + '.' + eventName, this.cmsEvents[eventName].bind(this)); | ||
} | ||
} | ||
|
||
/** | ||
* @func componentWillUnmount | ||
* @desc Unbind the event listeners we added in componentDidMount. | ||
*/ | ||
componentWillUnmount() { | ||
for (let eventName in this.cmsEvents) { | ||
$(document).off(this.cmsEventsNamespace + '.' + eventName); | ||
} | ||
} | ||
|
||
/** | ||
* @func _emitCmsEvent | ||
* @param string eventName | ||
* @param object|string|array|number [data] - Some data you want to pass with the event. | ||
* @desc Lets the outside world (legacy JavaScript) know something's happened in our component. | ||
*/ | ||
_emitCmsEvent(eventName, data) { | ||
if (typeof this.cmsEventsNamespace === 'undefined' || | ||
typeof eventName === 'undefined') { | ||
return; | ||
} | ||
|
||
$(document).trigger(this.cmsEventsNamespace + '.' + eventName, data); | ||
} | ||
|
||
} | ||
|
||
SilverStripeComponent.propTypes = { | ||
'cmsEvents': React.PropTypes.object, | ||
'cmsEventsNamespace': React.PropTypes.string | ||
}; | ||
|
||
export default SilverStripeComponent; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters