mirror of
https://github.com/ascribe/onion.git
synced 2025-01-26 01:32:16 +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() {
|
||||
// If onReset prop is defined from outside,
|
||||
// notify component that a form reset is happening.
|
||||
@ -69,9 +74,9 @@ let Form = React.createClass({
|
||||
this.props.onReset();
|
||||
}
|
||||
|
||||
for(let ref in this.refs) {
|
||||
if(typeof this.refs[ref].reset === 'function') {
|
||||
this.refs[ref].reset();
|
||||
for(let ref in this._refs) {
|
||||
if(typeof this._refs[ref].reset === 'function') {
|
||||
this._refs[ref].reset();
|
||||
}
|
||||
}
|
||||
this.setState(this.getInitialState());
|
||||
@ -124,8 +129,8 @@ let Form = React.createClass({
|
||||
getFormData() {
|
||||
let data = {};
|
||||
|
||||
for (let refName in this.refs) {
|
||||
const ref = this.refs[refName];
|
||||
for (let refName in this._refs) {
|
||||
const ref = this._refs[refName];
|
||||
|
||||
if (ref.state && 'value' in ref.state) {
|
||||
// An input can also provide an `Object` as a value
|
||||
@ -154,9 +159,9 @@ let Form = React.createClass({
|
||||
this.props.handleSuccess(response);
|
||||
}
|
||||
|
||||
for(let ref in this.refs) {
|
||||
if(this.refs[ref] && typeof this.refs[ref].handleSuccess === 'function'){
|
||||
this.refs[ref].handleSuccess(response);
|
||||
for(let ref in this._refs) {
|
||||
if(this._refs[ref] && typeof this._refs[ref].handleSuccess === 'function'){
|
||||
this._refs[ref].handleSuccess(response);
|
||||
}
|
||||
}
|
||||
this.setState({
|
||||
@ -168,8 +173,8 @@ let Form = React.createClass({
|
||||
handleError(err) {
|
||||
if (err.json) {
|
||||
for (let input in err.json.errors){
|
||||
if (this.refs && this.refs[input] && this.refs[input].state) {
|
||||
this.refs[input].setErrors(err.json.errors[input]);
|
||||
if (this._refs && this._refs[input] && this._refs[input].state) {
|
||||
this._refs[input].setErrors(err.json.errors[input]);
|
||||
} else {
|
||||
this.setState({errors: this.state.errors.concat(err.json.errors[input])});
|
||||
}
|
||||
@ -196,9 +201,9 @@ let Form = React.createClass({
|
||||
},
|
||||
|
||||
clearErrors() {
|
||||
for(let ref in this.refs){
|
||||
if (this.refs[ref] && typeof this.refs[ref].clearErrors === 'function'){
|
||||
this.refs[ref].clearErrors();
|
||||
for(let ref in this._refs){
|
||||
if (this._refs[ref] && typeof this._refs[ref].clearErrors === 'function'){
|
||||
this._refs[ref].clearErrors();
|
||||
}
|
||||
}
|
||||
this.setState({errors: []});
|
||||
@ -247,17 +252,19 @@ let Form = React.createClass({
|
||||
renderChildren() {
|
||||
return ReactAddons.Children.map(this.props.children, (child, i) => {
|
||||
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, {
|
||||
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,
|
||||
// We need this in order to make editable be overridable when setting it directly
|
||||
// on Property
|
||||
@ -338,10 +345,10 @@ let Form = React.createClass({
|
||||
const validatedFormInputs = {};
|
||||
|
||||
Object
|
||||
.keys(this.refs)
|
||||
.keys(this._refs)
|
||||
.forEach((refName) => {
|
||||
let refToValidate = {};
|
||||
const property = this.refs[refName];
|
||||
const property = this._refs[refName];
|
||||
const input = property.refs.input;
|
||||
const value = input.getDOMNode().value || input.state.value;
|
||||
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
|
||||
* of each uploader in the component
|
||||
@ -88,7 +93,7 @@ let RegisterPieceForm = React.createClass({
|
||||
|
||||
handleChangedThumbnail(thumbnailFile) {
|
||||
const { digitalWorkFile } = this.state;
|
||||
const { fineuploader } = this.refs.digitalWorkFineUploader.refs;
|
||||
const { fineuploader } = this._refs.digitalWorkFineUploader.refs;
|
||||
|
||||
fineuploader.setThumbnailForFileId(
|
||||
digitalWorkFile.id,
|
||||
@ -160,7 +165,7 @@ let RegisterPieceForm = React.createClass({
|
||||
ignoreFocus={true}
|
||||
label={getLangText('Your Work')}>
|
||||
<InputFineUploader
|
||||
ref={ref => this.refs.digitalWorkFineUploader = ref}
|
||||
ref={ref => this._refs.digitalWorkFineUploader = ref}
|
||||
keyRoutine={{
|
||||
url: AppConstants.serverUrl + 's3/key/',
|
||||
fileClass: 'digitalwork'
|
||||
@ -182,7 +187,7 @@ let RegisterPieceForm = React.createClass({
|
||||
name="thumbnail_file"
|
||||
expanded={this.isThumbnailDialogExpanded()}>
|
||||
<InputFineUploader
|
||||
ref={ref => this.refs.thumbnailFineUploader = ref}
|
||||
ref={ref => this._refs.thumbnailFineUploader = ref}
|
||||
fileInputElement={UploadButton({ className: 'btn btn-secondary btn-sm' })}
|
||||
createBlobRoutine={{
|
||||
url: ApiUrls.blob_thumbnails
|
||||
|
@ -77,6 +77,11 @@ const Property = React.createClass({
|
||||
};
|
||||
},
|
||||
|
||||
componentWillMount() {
|
||||
// Set up internal storage for callback refs
|
||||
this._refs = {};
|
||||
},
|
||||
|
||||
componentDidMount() {
|
||||
if(this.props.autoFocus) {
|
||||
this.handleFocus();
|
||||
@ -84,7 +89,7 @@ const Property = React.createClass({
|
||||
},
|
||||
|
||||
componentWillReceiveProps(nextProps) {
|
||||
let childInput = this.refs.input;
|
||||
let childInput = this._refs.input;
|
||||
|
||||
// For expanded there are actually three use cases:
|
||||
//
|
||||
@ -124,7 +129,7 @@ const Property = React.createClass({
|
||||
},
|
||||
|
||||
reset() {
|
||||
let input = this.refs.input;
|
||||
let input = this._refs.input;
|
||||
|
||||
// maybe do reset by reload instead of front end state?
|
||||
this.setState({value: this.state.initialValue});
|
||||
@ -179,11 +184,11 @@ const Property = React.createClass({
|
||||
}
|
||||
// skip the focus of non-input elements
|
||||
let nonInputHTMLElements = ['pre', 'div'];
|
||||
if (this.refs.input &&
|
||||
nonInputHTMLElements.indexOf(this.refs.input.getDOMNode().nodeName.toLowerCase()) > -1 ) {
|
||||
if (this._refs.input &&
|
||||
nonInputHTMLElements.indexOf(this._refs.input.getDOMNode().nodeName.toLowerCase()) > -1 ) {
|
||||
return;
|
||||
}
|
||||
this.refs.input.getDOMNode().focus();
|
||||
this._refs.input.getDOMNode().focus();
|
||||
this.setState({
|
||||
isFocused: true
|
||||
});
|
||||
@ -205,7 +210,7 @@ const Property = React.createClass({
|
||||
errors: null,
|
||||
|
||||
// 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((this.state.expanded && this.props.checkboxLabel) || !this.props.checkboxLabel) {
|
||||
return ReactAddons.Children.map(this.props.children, (child) => {
|
||||
// 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' && this.refs.input) {
|
||||
child.ref(this.refs.input);
|
||||
}
|
||||
|
||||
return React.cloneElement(child, {
|
||||
const childWithProps = React.cloneElement(child, {
|
||||
style,
|
||||
onChange: this.handleChange,
|
||||
onFocus: this.handleFocus,
|
||||
onBlur: this.handleBlur,
|
||||
setWarning: this.setWarning,
|
||||
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,
|
||||
setExpanded: this.setExpanded
|
||||
});
|
||||
|
||||
return childWithProps;
|
||||
});
|
||||
}
|
||||
},
|
||||
|
Loading…
Reference in New Issue
Block a user