JavaScript for WordPress Forums Gutenberg Development Toggle Control conditional

Viewing 5 posts - 1 through 5 (of 5 total)
  • Author
    Posts
  • #139251
    chrisdavies71
    Participant

    Hi Zac,

    I am attempting to build a custom Bootstrap inspired carousel block. I want to build a number of controls into the block to either show/hide things like indicators, controls etc. I have this set up in the inspector and it is mostly working.

    Where I am stuck is checking the state of the toggle and then outputting HTML based on that. I have put the code below but the workflow should be:

    1. If an image is not present show the media upload, if there is an image show it – done
    2. If an image is present and the toggle for controls is ‘true’ then add a block of HTML

    Hope that sort of makes sense. I have tried various bits and I can get the two separate bits to work but can not combine them properly.

    Any pointers much appreciated

    Chris

    /**
     * Block dependencies
     */
    import icon from './icon';
    import './style.scss';
    import './editor.scss';
    
    /**
     * Internal block libraries
     */
    const { __ } = wp.i18n;
    const { registerBlockType } = wp.blocks;
    const { InspectorControls, MediaUpload, MediaUploadCheck } = wp.blockEditor;
    const { PanelBody, PanelRow, FormToggle, Button, TextControl } = wp.components;
    const { Fragment } = wp.element;
    
    /**
     * Register block
     */
    export default registerBlockType(
        'elecwork/carousel',
        {
            title: __( 'Carousel', 'elecwork' ),
            description: __( 'A Bootstrap inspired carousel complete with indicators, controls and ability to link to a page.', 'elecwork' ),
            category: 'common',
            icon: {
              src: icon,
            },
            attributes: {
              carouselIndicators: {
                type: 'boolean',
                default: false,
              },
              carouselControls: {
                type: 'boolean',
                default: false,
              },
              carouselInterval: {
                type: 'string',
              },
              imgURL: {
                type: 'string',
                source: 'attribute',
                attribute: 'src',
                selector: 'img',
              },
              imgID: {
                type: 'number',
              },
              imgAlt: {
                type: 'string',
                source: 'attribute',
                attribute: 'alt',
                selector: 'img',
              }
            },
            keywords: [
                __( 'Carousel', 'elecwork' ),
                __( 'Slider', 'elecwork' ),
            ],
            edit: props => {
              const { attributes: { carouselIndicators, carouselControls, carouselInterval, imgURL, imgID, imgAlt }, attributes, className, isSelected, setAttributes } = props;
              const toggleIndicators = () => setAttributes( { carouselIndicators: ! carouselIndicators } );
              const toggleControls = () => setAttributes( { carouselControls: ! carouselControls } );
              const onSelectImage = img => { setAttributes( { imgID: img.id, imgURL: img.url, imgAlt: img.alt, } ); console.log(img) };
    
              return [
                <InspectorControls>
                  <PanelBody
                    title={ __( 'Settings', 'elecwork' ) }
                   >
                   <PanelRow>
                    <label
                      htmlFor="carousel-indicators-form-toggle"
                    >
                      { __( 'Show Indicators', 'elecwork' ) }
                    </label>
                    <FormToggle
                      id="carousel-indicators-form-toggle"
                      label={ __( 'Show Indicators', 'elecwork' ) }
                      checked={ carouselIndicators }
                      onChange={ toggleIndicators }
                     />
                  </PanelRow>
                  <PanelRow>
                    <label
                      htmlFor="carousel-controls-form-toggle"
                    >
                      { __( 'Show Controls', 'elecwork' ) }
                    </label>
                    <FormToggle
                      id="carousel-controls-form-toggle"
                      label={ __( 'Show Controls', 'elecwork' ) }
                      checked={ carouselControls }
                      onChange={ toggleControls }
                     />
                  </PanelRow>
                  <PanelRow>
                    <TextControl
                      label={__("Slide Interval", "elecwork")}
                      help={__("Text control help text", "elecwork")}
                      value={ carouselInterval }
                      onChange={ carouselInterval => setAttributes({ carouselInterval }) }
                    />
                  </PanelRow>
                </PanelBody>
              </InspectorControls>,
              <div className={ className }>
    
                { ! imgID ? (
    
                      <MediaUploadCheck>
                        <MediaUpload
                          onSelect={ onSelectImage }
                          type="image"
                          value={ props.attributes.imgID }
                          //allowedTypes={ 'image' }
                          render={ ( { open } ) => (
                            <Button isPrimary onClick={ open }> Open Media Library </Button>
                          ) }
                        />
                      </MediaUploadCheck>
    
                      ) : (
    
                      <Fragment>
                      <p class="image-wrapper">
                        <img
                          src={ imgURL }
                          alt={ imgAlt }
                        />
                      </p>
                      </Fragment>,
    
                     carouselControls && (
                      <Fragment>
                        <a className="carousel-control-prev" href="#carouselExampleControls" role="button" data-slide="prev">
                          <span className="carousel-control-prev-icon" aria-hidden="true"></span>
                          <span className="sr-only">Previous</span>
                        </a>
                        <a className="carousel-control-next" href="#carouselExampleControls" role="button" data-slide="next">
                          <span className="carousel-control-next-icon" aria-hidden="true"></span>
                          <span className="sr-only">Next</span>
                        </a>
                      </Fragment>
    
                    ) //end carousel controls check
    
                  ) //end if has image
    
                }
    
                </div>
              ];
            },
            save: props => {
              const { attributes: { carouselIndicators, carouselControls, carouselInterval, imgURL, imgAlt }, attributes, className,} = props;
    
              return (
                <div className={ className }>
    
                  {
                    <p>
                      <img
                        src={ imgURL }
                        alt={imgAlt }
                      />
                    </p>,
    
                    carouselControls == true && (
                      <Fragment>
                      <a className="carousel-control-prev" href="#carouselExampleControls" role="button" data-slide="prev">
                        <span className="carousel-control-prev-icon" aria-hidden="true"></span>
                        <span className="sr-only">Previous</span>
                      </a>
                      <a className="carousel-control-next" href="#carouselExampleControls" role="button" data-slide="next">
                        <span className="carousel-control-next-icon" aria-hidden="true"></span>
                        <span className="sr-only">Next</span>
                      </a>
                      </Fragment>
                    )
                  }
                </div>
              );
            },
        },
    );
    
    #139252
    Zac Gordon
    Keymaster

    What is it that is not working. You’re on the right track of simplifying it till it works then adding the complexities back in, finding where it breaks. But what is the specific error or problem you’re having?

    #139254
    chrisdavies71
    Participant

    Hi Zac,

    If I take it back to basically what you have in the course examples it works – as in the image appears in the block as expected.

    I can also add the HTML for the controls and when the image appears in the block so do the controls (expected behaviour)

    When I try and add the conditional around the controls HTML the image no longer appears in the block. It seems this bit is what is tripping me up:

    ) : (
    
                      <Fragment>
                      <p class="image-wrapper">
                        <img
                          src={ imgURL }
                          alt={ imgAlt }
                        />
                      </p>
                      </Fragment>,
    
                     carouselControls && ( <-- THIS IS WHERE IT GOES WRONG
                      <Fragment>
                        <a className="carousel-control-prev" href="#carouselExampleControls" role="button" data-slide="prev">
                          <span className="carousel-control-prev-icon" aria-hidden="true"></span>
                          <span className="sr-only">Previous</span>
                        </a>
                        <a className="carousel-control-next" href="#carouselExampleControls" role="button" data-slide="next">
                          <span className="carousel-control-next-icon" aria-hidden="true"></span>
                          <span className="sr-only">Next</span>
                        </a>
                      </Fragment>
    
                    ) //end carousel controls check
    
                  ) //end if has image
    • This reply was modified 4 months, 1 week ago by chrisdavies71. Reason: Code tidy up
    #139256
    Zac Gordon
    Keymaster

    Is there an error you’re getting or does it just not render. It looks like you’re returning sybling elements. Try nesting both those in a single element perhaps? Also, you’re going from JSX back to JS so curly braces may be necessary as well.

    Just for background context. What is your familiarity with JSX conditionals?

    #139259
    chrisdavies71
    Participant

    Hi Zac,

    I was not getting any error it was just not rendering the image.

    Just starting out really with Gutenberg/JSX but I found this link 7-ways-to-implement-conditional-rendering-in-react-applications and used the Ternary Operators solution.

    Code now looks like this and works

    ) : (
    
                      <Fragment>
                      <p class="image-wrapper">
                        <img
                          src={ imgURL }
                          alt={ imgAlt }
                        />
                      </p>
    
                      { carouselControls ?
    
                        <Fragment>
                        <a className="carousel-control-prev" href="#carouselExampleControls" role="button" data-slide="prev">
                          <span className="carousel-control-prev-icon" aria-hidden="true"></span>
                          <span className="sr-only">Previous</span>
                        </a>
                        <a className="carousel-control-next" href="#carouselExampleControls" role="button" data-slide="next">
                          <span className="carousel-control-next-icon" aria-hidden="true"></span>
                          <span className="sr-only">Next</span>
                        </a>
                        </Fragment>
    
                      : ''
                      }
    
                      </Fragment>
    
                  ) //end if has image
    

    It could probably be tidied up in places. Thanks for the help though.

    Chris

Viewing 5 posts - 1 through 5 (of 5 total)
  • You must be logged in to reply to this topic.