mirror of
https://github.com/ascribe/onion.git
synced 2025-02-14 21:10:27 +01:00
Fix callback ref propagation to parent components
This commit is contained in:
parent
dcdae7b7b1
commit
65f7d02e6d
@ -62,6 +62,11 @@ let Form = React.createClass({
|
|||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
|
componentWillMount() {
|
||||||
|
// Set up internal storage for callback refs
|
||||||
|
this._refs = {};
|
||||||
|
},
|
||||||
|
|
||||||
reset() {
|
reset() {
|
||||||
// If onReset prop is defined from outside,
|
// If onReset prop is defined from outside,
|
||||||
// notify component that a form reset is happening.
|
// notify component that a form reset is happening.
|
||||||
@ -69,9 +74,9 @@ let Form = React.createClass({
|
|||||||
this.props.onReset();
|
this.props.onReset();
|
||||||
}
|
}
|
||||||
|
|
||||||
for(let ref in this.refs) {
|
for(let ref in this._refs) {
|
||||||
if(typeof this.refs[ref].reset === 'function') {
|
if(typeof this._refs[ref].reset === 'function') {
|
||||||
this.refs[ref].reset();
|
this._refs[ref].reset();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.setState(this.getInitialState());
|
this.setState(this.getInitialState());
|
||||||
@ -124,8 +129,8 @@ let Form = React.createClass({
|
|||||||
getFormData() {
|
getFormData() {
|
||||||
let data = {};
|
let data = {};
|
||||||
|
|
||||||
for (let refName in this.refs) {
|
for (let refName in this._refs) {
|
||||||
const ref = this.refs[refName];
|
const ref = this._refs[refName];
|
||||||
|
|
||||||
if (ref.state && 'value' in ref.state) {
|
if (ref.state && 'value' in ref.state) {
|
||||||
// An input can also provide an `Object` as a value
|
// An input can also provide an `Object` as a value
|
||||||
@ -154,9 +159,9 @@ let Form = React.createClass({
|
|||||||
this.props.handleSuccess(response);
|
this.props.handleSuccess(response);
|
||||||
}
|
}
|
||||||
|
|
||||||
for(let ref in this.refs) {
|
for(let ref in this._refs) {
|
||||||
if(this.refs[ref] && typeof this.refs[ref].handleSuccess === 'function'){
|
if(this._refs[ref] && typeof this._refs[ref].handleSuccess === 'function'){
|
||||||
this.refs[ref].handleSuccess(response);
|
this._refs[ref].handleSuccess(response);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.setState({
|
this.setState({
|
||||||
@ -168,8 +173,8 @@ let Form = React.createClass({
|
|||||||
handleError(err) {
|
handleError(err) {
|
||||||
if (err.json) {
|
if (err.json) {
|
||||||
for (let input in err.json.errors){
|
for (let input in err.json.errors){
|
||||||
if (this.refs && this.refs[input] && this.refs[input].state) {
|
if (this._refs && this._refs[input] && this._refs[input].state) {
|
||||||
this.refs[input].setErrors(err.json.errors[input]);
|
this._refs[input].setErrors(err.json.errors[input]);
|
||||||
} else {
|
} else {
|
||||||
this.setState({errors: this.state.errors.concat(err.json.errors[input])});
|
this.setState({errors: this.state.errors.concat(err.json.errors[input])});
|
||||||
}
|
}
|
||||||
@ -196,9 +201,9 @@ let Form = React.createClass({
|
|||||||
},
|
},
|
||||||
|
|
||||||
clearErrors() {
|
clearErrors() {
|
||||||
for(let ref in this.refs){
|
for(let ref in this._refs){
|
||||||
if (this.refs[ref] && typeof this.refs[ref].clearErrors === 'function'){
|
if (this._refs[ref] && typeof this._refs[ref].clearErrors === 'function'){
|
||||||
this.refs[ref].clearErrors();
|
this._refs[ref].clearErrors();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.setState({errors: []});
|
this.setState({errors: []});
|
||||||
@ -247,17 +252,19 @@ let Form = React.createClass({
|
|||||||
renderChildren() {
|
renderChildren() {
|
||||||
return ReactAddons.Children.map(this.props.children, (child, i) => {
|
return ReactAddons.Children.map(this.props.children, (child, i) => {
|
||||||
if (child) {
|
if (child) {
|
||||||
// Since refs will be overwritten by this functions return statement,
|
|
||||||
// we still want to be able to define refs for nested `Form` or `Property`
|
|
||||||
// children, which is why we're upfront simply invoking the callback-ref-
|
|
||||||
// function before overwriting it.
|
|
||||||
if(typeof child.ref === 'function' && this.refs[child.props.name]) {
|
|
||||||
child.ref(this.refs[child.props.name]);
|
|
||||||
}
|
|
||||||
|
|
||||||
return React.cloneElement(child, {
|
return React.cloneElement(child, {
|
||||||
handleChange: this.handleChangeChild,
|
handleChange: this.handleChangeChild,
|
||||||
ref: child.props.name,
|
ref: (ref) => {
|
||||||
|
this._refs[child.props.name] = ref;
|
||||||
|
|
||||||
|
// Since refs will be overwritten by this functions return statement,
|
||||||
|
// we still want to be able to define refs for nested `Form` or `Property`
|
||||||
|
// children, which is why we're upfront simply invoking the callback-ref-
|
||||||
|
// function before overwriting it.
|
||||||
|
if (typeof child.ref === 'function') {
|
||||||
|
child.ref(ref);
|
||||||
|
}
|
||||||
|
},
|
||||||
key: i,
|
key: i,
|
||||||
// We need this in order to make editable be overridable when setting it directly
|
// We need this in order to make editable be overridable when setting it directly
|
||||||
// on Property
|
// on Property
|
||||||
@ -338,10 +345,10 @@ let Form = React.createClass({
|
|||||||
const validatedFormInputs = {};
|
const validatedFormInputs = {};
|
||||||
|
|
||||||
Object
|
Object
|
||||||
.keys(this.refs)
|
.keys(this._refs)
|
||||||
.forEach((refName) => {
|
.forEach((refName) => {
|
||||||
let refToValidate = {};
|
let refToValidate = {};
|
||||||
const property = this.refs[refName];
|
const property = this._refs[refName];
|
||||||
const input = property.refs.input;
|
const input = property.refs.input;
|
||||||
const value = input.getDOMNode().value || input.state.value;
|
const value = input.getDOMNode().value || input.state.value;
|
||||||
const { max,
|
const { max,
|
||||||
|
@ -58,6 +58,11 @@ let RegisterPieceForm = React.createClass({
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
componentWillMount() {
|
||||||
|
// Set up internal storage for callback refs
|
||||||
|
this._refs = {};
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method is overloaded so that we can track the ready-state
|
* This method is overloaded so that we can track the ready-state
|
||||||
* of each uploader in the component
|
* of each uploader in the component
|
||||||
@ -88,7 +93,7 @@ let RegisterPieceForm = React.createClass({
|
|||||||
|
|
||||||
handleChangedThumbnail(thumbnailFile) {
|
handleChangedThumbnail(thumbnailFile) {
|
||||||
const { digitalWorkFile } = this.state;
|
const { digitalWorkFile } = this.state;
|
||||||
const { fineuploader } = this.refs.digitalWorkFineUploader.refs;
|
const { fineuploader } = this._refs.digitalWorkFineUploader.refs;
|
||||||
|
|
||||||
fineuploader.setThumbnailForFileId(
|
fineuploader.setThumbnailForFileId(
|
||||||
digitalWorkFile.id,
|
digitalWorkFile.id,
|
||||||
@ -160,7 +165,7 @@ let RegisterPieceForm = React.createClass({
|
|||||||
ignoreFocus={true}
|
ignoreFocus={true}
|
||||||
label={getLangText('Your Work')}>
|
label={getLangText('Your Work')}>
|
||||||
<InputFineUploader
|
<InputFineUploader
|
||||||
ref={ref => this.refs.digitalWorkFineUploader = ref}
|
ref={ref => this._refs.digitalWorkFineUploader = ref}
|
||||||
keyRoutine={{
|
keyRoutine={{
|
||||||
url: AppConstants.serverUrl + 's3/key/',
|
url: AppConstants.serverUrl + 's3/key/',
|
||||||
fileClass: 'digitalwork'
|
fileClass: 'digitalwork'
|
||||||
@ -182,7 +187,7 @@ let RegisterPieceForm = React.createClass({
|
|||||||
name="thumbnail_file"
|
name="thumbnail_file"
|
||||||
expanded={this.isThumbnailDialogExpanded()}>
|
expanded={this.isThumbnailDialogExpanded()}>
|
||||||
<InputFineUploader
|
<InputFineUploader
|
||||||
ref={ref => this.refs.thumbnailFineUploader = ref}
|
ref={ref => this._refs.thumbnailFineUploader = ref}
|
||||||
fileInputElement={UploadButton({ className: 'btn btn-secondary btn-sm' })}
|
fileInputElement={UploadButton({ className: 'btn btn-secondary btn-sm' })}
|
||||||
createBlobRoutine={{
|
createBlobRoutine={{
|
||||||
url: ApiUrls.blob_thumbnails
|
url: ApiUrls.blob_thumbnails
|
||||||
|
@ -77,6 +77,11 @@ const Property = React.createClass({
|
|||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
|
componentWillMount() {
|
||||||
|
// Set up internal storage for callback refs
|
||||||
|
this._refs = {};
|
||||||
|
},
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
if(this.props.autoFocus) {
|
if(this.props.autoFocus) {
|
||||||
this.handleFocus();
|
this.handleFocus();
|
||||||
@ -84,7 +89,7 @@ const Property = React.createClass({
|
|||||||
},
|
},
|
||||||
|
|
||||||
componentWillReceiveProps(nextProps) {
|
componentWillReceiveProps(nextProps) {
|
||||||
let childInput = this.refs.input;
|
let childInput = this._refs.input;
|
||||||
|
|
||||||
// For expanded there are actually three use cases:
|
// For expanded there are actually three use cases:
|
||||||
//
|
//
|
||||||
@ -124,7 +129,7 @@ const Property = React.createClass({
|
|||||||
},
|
},
|
||||||
|
|
||||||
reset() {
|
reset() {
|
||||||
let input = this.refs.input;
|
let input = this._refs.input;
|
||||||
|
|
||||||
// maybe do reset by reload instead of front end state?
|
// maybe do reset by reload instead of front end state?
|
||||||
this.setState({value: this.state.initialValue});
|
this.setState({value: this.state.initialValue});
|
||||||
@ -179,11 +184,11 @@ const Property = React.createClass({
|
|||||||
}
|
}
|
||||||
// skip the focus of non-input elements
|
// skip the focus of non-input elements
|
||||||
let nonInputHTMLElements = ['pre', 'div'];
|
let nonInputHTMLElements = ['pre', 'div'];
|
||||||
if (this.refs.input &&
|
if (this._refs.input &&
|
||||||
nonInputHTMLElements.indexOf(this.refs.input.getDOMNode().nodeName.toLowerCase()) > -1 ) {
|
nonInputHTMLElements.indexOf(this._refs.input.getDOMNode().nodeName.toLowerCase()) > -1 ) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.refs.input.getDOMNode().focus();
|
this._refs.input.getDOMNode().focus();
|
||||||
this.setState({
|
this.setState({
|
||||||
isFocused: true
|
isFocused: true
|
||||||
});
|
});
|
||||||
@ -205,7 +210,7 @@ const Property = React.createClass({
|
|||||||
errors: null,
|
errors: null,
|
||||||
|
|
||||||
// also update initialValue in case of the user updating and canceling its actions again
|
// also update initialValue in case of the user updating and canceling its actions again
|
||||||
initialValue: this.refs.input.getDOMNode().value
|
initialValue: this._refs.input.getDOMNode().value
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -262,25 +267,29 @@ const Property = React.createClass({
|
|||||||
// if the component is actually being shown (!== 'expanded === false')
|
// if the component is actually being shown (!== 'expanded === false')
|
||||||
if((this.state.expanded && this.props.checkboxLabel) || !this.props.checkboxLabel) {
|
if((this.state.expanded && this.props.checkboxLabel) || !this.props.checkboxLabel) {
|
||||||
return ReactAddons.Children.map(this.props.children, (child) => {
|
return ReactAddons.Children.map(this.props.children, (child) => {
|
||||||
// Since refs will be overriden by this functions return statement,
|
const childWithProps = React.cloneElement(child, {
|
||||||
// we still want to be able to define refs for nested `Form` or `Property`
|
|
||||||
// children, which is why we're upfront simply invoking the callback-ref-
|
|
||||||
// function before overriding it.
|
|
||||||
if(typeof child.ref === 'function' && this.refs.input) {
|
|
||||||
child.ref(this.refs.input);
|
|
||||||
}
|
|
||||||
|
|
||||||
return React.cloneElement(child, {
|
|
||||||
style,
|
style,
|
||||||
onChange: this.handleChange,
|
onChange: this.handleChange,
|
||||||
onFocus: this.handleFocus,
|
onFocus: this.handleFocus,
|
||||||
onBlur: this.handleBlur,
|
onBlur: this.handleBlur,
|
||||||
setWarning: this.setWarning,
|
setWarning: this.setWarning,
|
||||||
disabled: !this.props.editable,
|
disabled: !this.props.editable,
|
||||||
ref: 'input',
|
ref: (ref) => {
|
||||||
|
this._refs.input = ref;
|
||||||
|
|
||||||
|
// Since refs will be overriden by this functions return statement,
|
||||||
|
// we still want to be able to define refs for nested `Form` or `Property`
|
||||||
|
// children, which is why we're upfront simply invoking the callback-ref-
|
||||||
|
// function before overriding it.
|
||||||
|
if (typeof child.ref === 'function') {
|
||||||
|
child.ref(ref);
|
||||||
|
}
|
||||||
|
},
|
||||||
name: this.props.name,
|
name: this.props.name,
|
||||||
setExpanded: this.setExpanded
|
setExpanded: this.setExpanded
|
||||||
});
|
});
|
||||||
|
|
||||||
|
return childWithProps;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
Loading…
x
Reference in New Issue
Block a user