Reputation: 4691
I am creating a Gutenberg block with many attributes and try to create a generic function for attributes that can be changed with an input field. For an attribute title
I have:
<RichText
onChange={this.props.onTitleChange}
value={this.props.title}
/>
and
function onTitleChange(value) {
setAttributes({title: value});
}
This works. Now though I wish to create a generic function where in setAttributes()
title
can be anything I pass from the React onChange
. I tried with another function onValueChange
:
<RichText
onChange={this.props.onValueChange.bind("title")}
value={this.props.title}
/>
and
function onValueChange(value) {
setAttributes({this: value});
}
This won't work because 'this' is not an attribute of my block. Even though this
in my function onValueChange
does equal 'title', which was passed with the bind()
function.
I am not sure if what I am trying to do is possible, because I don't fully understand the setAttributes()
function, but if it can be done, it would save a lot time and extra code, because otherwise I would have to create a onXChange()
function for all of my attributes. So my question is: how can I set a value on a dynamic attribute with setAttributes()
?
Upvotes: 1
Views: 5843
Reputation: 1
This was fantastic finding the [this] in the answer here. I was trying to take this a step further and that made it simpler for me!
Now I have one component I can use over and over for all the attributes I want.
export const CustomComponents = {
CustomRangeControl: (val, attribute, setAttributes) => {
return (
<RangeControl
label={[attribute]}
value={val}
onChange={(value) => setAttributes({[attribute]: value}) }
min={20}
max={800}
/>
);
}
}
And now I can add it to my blocks like this
<InspectorControls>
<PanelBody ...>
{CustomComponents.CustomRangeControl(width, "width", setAttributes)}
{CustomComponents.CustomRangeControl(height, "height", setAttributes)}
...
</PanelBody>
</InspectorControls>
Upvotes: 0
Reputation: 4691
It turns out all I had to do was to wrap this
in brackets, so:
function onValueChange(value) {
setAttributes({[this]: value});
}
Keeping the bound attribute:
onChange={onValueChange.bind('title')}
Another option is to use setAttributes
inline like so:
onChange={ title => setAttributes( { title } ) }
make sure to changetitle
to the name of the attribute.
Upvotes: 2
Reputation: 1021
Currently i can think of this :
class MyComponent extends React.Component {
constructor(props) {
super(props);
// create a ref to store the textInput DOM element
this.textInput = React.createRef();
}
render() {
// tell React that we want to associate the ref
// with the `textInput` that we created in the constructor
<RichText
onChange={ ()=> this.props.onValueChange("title",value) }
value={this.props.title}
ref={this.textInput}
/>
}
}
function onValueChange(property ,value) {
let element = ReactDOM.findDOMNode(this.refs.textInput);
element.setAttributes({property: value});
}
PS: Not Sure wheather this is going to work but yeah you can give a try.
Upvotes: 0