The reason why the block editor uses the default value — for the max_level
(“Maximum level”) attribute only — instead of the one parsed from the (block comment delimiter in the) saved post content, is because in the parsed/saved attributes, max_level
is invalid.
Why is it invalid: Because the type of the attribute (value) doesn’t match the one defined when the block is registered — max_level: { type: 'integer', ... }
.
And why doesn’t it match, is because this part which updates the attribute with a value that is a string:
// "level" here is an input value, and input values are string unless
// explicitly converted to another type (boolean, number, etc.):
onChange={ ( level ) => props.setAttributes( { max_level: level } ) }
Which then, for instance when the “Including H3” is selected as the “Maximum level”, results in "max_level":"3"
instead of the correct one, "max_level":3
:
-
Bad —
max_level
is a string:<!-- wp:simpletoc/toc {"max_level":"3"} /-->
-
Good —
max_level
is an integer:<!-- wp:simpletoc/toc {"max_level":3} /-->
So be sure to respect the attribute type and in your case, you would want to use Number( level )
like so:
props.setAttributes( { max_level: Number( level ) } )
BTW, I could’ve just pointed you to my answer here, but I thought it’d be better if I write an answer specific to this very question. 🙂
Additional Notes
-
The
ServerSideRender
component useswp.element.RawHTML()
which wraps the output in adiv
, hence you shouldn’t wrap theServerSideRender
in ap
, which (in my case) resulted in an error (in the console) which says, “<div>
cannot be a descendant of<p>
” ( in fact, the regular HTML<p><div>something</div></p>
is indeed invalid 🙂 ). So,// Instead of this: <p><ServerSideRender .../></p> // Use a div or Fragment as a wrapper: <div><ServerSideRender .../></div> <><ServerSideRender .../></> // Or simply, no wrapper: <ServerSideRender .../>