Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Dynamic form content #11

Open
transitive-bullshit opened this issue Feb 6, 2016 · 5 comments
Open

Dynamic form content #11

transitive-bullshit opened this issue Feb 6, 2016 · 5 comments
Labels

Comments

@transitive-bullshit
Copy link

First off this library is really great.

I ran into an issue where Modals with custom content dependent on container state aren't re-rendered due to the ModalWidget cloning the elements once at mount time. I was hoping to have a more dynamic modal which would show / hide a TextAreaWidget dependent on the value of a SwitchWidget ala below:

         <GiftedForm.ModalWidget
            ref="customMessageModal"
            title='Custom Message'
            displayValue='hasCustomMessage'
            underlayColor='royalblue'
            transformValue={(value) => (value ? 'on' : 'off') }
          >
            <GiftedForm.SeparatorWidget />

            <GiftedForm.SwitchWidget
              name='hasCustomMessage'
              title='Custom Message? (+ $1.00)'
              value={this.state.hasCustomMessage}
              onValueChange={(value) => {
                this.setState({ hasCustomMessage: value })
              }}
            />

            {this.state.hasCustomMessage ? <GiftedForm.TextAreaWidget
              name='customMessage'
              value={this.state.customMessage}
              placeholder='Custom Message'
              maxLength={120}
              multiline={true}
              style={styles.customMessage}
              onChangeText={(value) => {
                this.setState({ customMessage: value })
              }}
            /> : <View />}

            <GiftedForm.NoticeWidget title='Optionally add a custom welcome message that will be sent before any other messages. (Max 120 characters)' />
          </GiftedForm.ModalWidget>

Any idea how to make the modal contents more dynamic?

Thanks!

@FaridSafi
Copy link
Owner

Hello @fisch0920, I can't test your code right now but I think your onValueChange is overwritten by https://github.com/FaridSafi/react-native-gifted-form/blob/master/widgets/SwitchWidget.js#L61
You must replace line 61 by something like :

onValueChange={(value) => {
  this._onChange(value);
  this.props.onChange(value);
}} 

then to do

onChange={(value) => {
  this.setState({ hasCustomMessage: value })
}}

then to do something similar for TextAreaWidget

If it works, please submit a pull request

@transitive-bullshit
Copy link
Author

Hey @FaridSafi, thanks for the quick feedback and I know what you mean. I've already changed my fork to allow onValueChange overrides in addition to calling WidgetMixin._onChange, but the base issue remains that updating the parent state doesn't update the cloned modal's child states.

@transitive-bullshit
Copy link
Author

If I change ContainerMixin as follows, dynamic content within the form itself and modals works as expected.

From:

componentWillMount() {
    this._childrenWithProps = React.Children.map(this.props.children, (child) => {
      return React.cloneElement(child, {
        formStyles: this.props.formStyles,
        openModal: this.props.openModal,
        formName: this.props.formName,
        navigator: this.props.navigator,
        onFocus: this.handleFocus,
        onBlur: this.handleBlur,
      });
    });
  },

  _renderContainerView() {
    if (this.props.scrollEnabled === true) {
      return (
        <ScrollView
          ref='container'
          style={[(this.props.isModal === false ? styles.containerView : styles.modalView), this.props.style]}
          automaticallyAdjustContentInsets={false}
          keyboardDismissMode='on-drag'
          keyboardShouldPersistTaps={true}

          onTouchStart={this.props.scrollOnTap === true ? this._onTouchStart : null}
          onScroll={this.props.scrollOnTap === true ? this._onScroll : null}
          scrollEventThrottle={this.props.scrollOnTap === true ? 200 : 0}

          {...this.props}
        >
          {this._childrenWithProps}
        </ScrollView>
      );
    }
    return (
      <View
        ref='container'
        style={[(this.props.isModal === false ? styles.containerView : styles.modalView), this.props.style]}
        keyboardDismissMode='on-drag' // its working on View ?

        {...this.props}
      >
        {this._childrenWithProps}
      </View>
    );
  },

To:

componentWillMount() {
    this._childrenWithProps = () => React.Children.map(this.props.children, (child) => {
      return React.cloneElement(child, {
        formStyles: this.props.formStyles,
        openModal: this.props.openModal,
        formName: this.props.formName,
        navigator: this.props.navigator,
        onFocus: this.handleFocus,
        onBlur: this.handleBlur,
      });
    });
  },

  _renderContainerView() {
    if (this.props.scrollEnabled === true) {
      return (
        <ScrollView
          ref='container'
          style={[(this.props.isModal === false ? styles.containerView : styles.modalView), this.props.style]}
          automaticallyAdjustContentInsets={false}
          keyboardDismissMode='on-drag'
          keyboardShouldPersistTaps={true}

          onTouchStart={this.props.scrollOnTap === true ? this._onTouchStart : null}
          onScroll={this.props.scrollOnTap === true ? this._onScroll : null}
          scrollEventThrottle={this.props.scrollOnTap === true ? 200 : 0}

          {...this.props}
        >
          {this._childrenWithProps()}
        </ScrollView>
      );
    }
    return (
      <View
        ref='container'
        style={[(this.props.isModal === false ? styles.containerView : styles.modalView), this.props.style]}
        keyboardDismissMode='on-drag' // its working on View ?

        {...this.props}
      >
        {this._childrenWithProps()}
      </View>
    );
  }

Note that this is just making the childrenWithProps cloning dynamic instead of only at mount time. This change is necessary for my use case to function properly as I want to rely on external state to update the form's contents, not just the form's internal state representation. @FaridSafi what do you think of this change? Will it have any unexpected side effects?

@transitive-bullshit transitive-bullshit changed the title Modal with dynamic content Dynamic form content Feb 6, 2016
@FaridSafi
Copy link
Owner

Looks good, can you enable it as an option (something like dynamicForm={true}) and submit a PR please ?
We can include this in next version.

@FaridSafi
Copy link
Owner

Also, I think you should use widgetStyles prop instead of style for the TextAreaWidget

widgetStyles={{
  textArea: styles.customMessage
}}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants