WordPress / gutenberg

The Block Editor project for WordPress and beyond. Plugin is available from the official repository.
https://wordpress.org/gutenberg/
Other
10.32k stars 4.12k forks source link

Block editor: request for "input with button" component #22389

Open JohnRDOrazio opened 4 years ago

JohnRDOrazio commented 4 years ago

Until I learn how to build my own react components for the block editor, I would like to request an input with button component for the block editor, especially for the InspectorTools area. For the time being I am quite hackishly creating a TextControl component input, then creating a Button component (which however, even though being a child of the same PanelRow component, is not an immediate sibling of the text input, but rather of the div parent of the text input). Then when the InspectorControls are rendered (upon clicking on my registered block) I am using jQuery to move the button and place it next to the input as an immediate sibling. This seems to me to be quite a hackish approach, it would be nice to have this kind of component in the WordPress block editor... Basically I'm not using any onChange events on the TextControl input, I'm only using the Button component's onClick event.

I understand this is a pretty specific use case, basically this is a search input, clicking on the button will gather results from an external service based on the text input, and then the user (site admin / editor) will be able to choose elements from the results to insert into the gutenberg block.

Here is a screenshot of my hackish result. screenshot wordpress block editor inspectorcontrols input with button

JohnRDOrazio commented 3 years ago

Having learned a little more about react and react components in gutenberg, I have succeeded in implementing this in my plugin. Perhaps it could still be considered as a component in the components system, in any case here is how I did it:

const SearchBoxControl = ( props ) => {
    return (createElement('div', { className: 'customSearchBoxCtl' }, 
        createElement('input',{
            type: 'search',
            placeholder: 'search term here',
            className: 'customSearchBoxInput'
        }),
        createElement(Button,{
            icon: 'search',
            isPrimary: true,
            onClick: props.onButtonClick,
            className: 'customSearchBoxBtn'
        })
    )
    );
}

And in the stylesheet for the block:

.customSearchBoxCtl input {
    width: 80% !important;
    height: 36px;
    border-top-right-radius: 0 !important;
    border-bottom-right-radius: 0 !important;
}

.customSearchBoxBtn {
    position: relative;
    top: 4px;
    left: -2px;
    border-radius: 4px;
    border-top-left-radius: 0;
    border-bottom-left-radius: 0;
}

.customSearchBoxCtl input:focus + .customSearchBoxBtn {
    border-color: #007cba;
    box-shadow: 0 0 0 1px #007cba;
    outline: 2px solid transparent;
}

Then, to implement it in my InspectorControls:

createElement(PanelRow, {},
    createElement(BaseControl, {
            label: 'Search for possible candidates for your team',
            help: 'Type the desired skills. When you click on the search button you will be presented with a list of candidates to choose from. Choosing one will insert the candidate into the team block.'
        }, createElement(SearchBoxControl, { onButtonClick: doKeywordSearch })
    )
)

const doKeywordSearch = function(){
  //implement your backend, ajax, API, route, whatever kind of search you need to do here
  //I'm getting the search term by targeting the input using jQuery, though I'm sure there's a better react way of doing this, maybe with useState
  let keyword = $('.customSearchBoxCtl input').val();
}