I found that there was only illustration for placeholder component props in https://docs.slatejs.org/reference/components/placeholder.html. And I couldn't find out some examples in slate codebase.
Now I use the default paragraph type placeholder in my app, which works well in examples/rtl.
I would like to know if slate could provide some demo or example code for Placeholder component ? Then I can do more customized things.
Thanks a lot. : )
Here's how I used it in my project:
Placeholder.js
// tools
import React from "react"
import { Placeholder } from "slate"
// return
export default class extends React.Component {
render(){
const { node, state, parent } = this.props
return (
<Placeholder
firstOnly={ true }
parent={ parent }
node={ node }
state={ state }
style={{ opacity: "0.65" }}
>
{ this.props.children }
</Placeholder>
)
}
}
schema.js
// tools
import React from "react"
// components
import Placeholder from "./containers/Placeholder"
// return
export const schema = {
nodes: {
paragraph: props => <p { ...props.attributes } style={{ position: "relative" }}><Placeholder { ...props }>Write your story...</Placeholder>{ props.children }</p>
}
}
... Then added this schema to the state.
Thanks for @dmitrizzle 's example. But I think that it is a little bit obscure to know use Placeholder in editor schema. And the props parent and node are should not be cared by developers. Using in schema is more like customizing the content paragraph.
Why not just give the customized component as prop placeholder={<MyComponent />} ? It might be easier for user to learn.
@dmitrizzle example misses two things. The first one is that Placeholder is implemented in slate-react, not slate; the second is that style needs position: 'inherit', because typically, the first few elements are occupied with block/mark controls, and position: absolute; top: 0; left: 0 will place the placeholder at wrong place
UPD. I've implemented my own version of Placeholder wrapper (in TypeScript), which solves a problem with remaining Placeholder in a focused Editor (until one element is added). Hope it will be usefull
import * as React from 'react';
import { Component } from 'react';
// Components
import { Placeholder } from 'slate-react';
interface SlatePlaceholderProps {
firstOnly?: boolean;
node: React.ReactNode;
parent?: React.ReactNode;
style?: any;
state: any;
editor?: any;
className?: string;
}
interface SlatePlaceholderState {
visible: boolean;
}
export class SlatePlaceholder extends Component<SlatePlaceholderProps, SlatePlaceholderState> {
static defaultProps = {
firstOnly: true
}
state = {
visible: true
}
private _isMounted: boolean = false;
componentDidMount() {
const editor = this.props.editor;
if (editor != undefined) {
editor.onFocus = this.hidePlaceholder;
editor.onBlur = this.showPlaceholder;
this._isMounted = true;
}
}
componentWillUnmount() {
this._isMounted = false;
const editor = this.props.editor;
if (editor != undefined) {
editor.forceUpdate(); // this is important to allow the placeholder to be hidden after editor is focused the first time
}
}
private hidePlaceholder = () => {
if (this._isMounted) {
this.setState({ visible: false });
}
}
private showPlaceholder = () => {
if (this._isMounted) {
this.setState({ visible: true });
}
}
render() {
const { children, ...props } = this.props;
return (
this.state.visible ?
<Placeholder { ...props }>{children}</Placeholder> :
null
);
}
}
and is used in Schema as
export const Schema = (options: { placeholder?} = {}) => ({
nodes: {
...
'paragraph': props => <p {...props.attributes}>
{options && options.placeholder ?
<SlatePlaceholder
firstOnly={true}
editor={props.editor}
node={props.node}
parent={props.parent}
state={props.state}
style={{ opacity: '0.65', position: 'inherit' }}>{options.placeholder}</Placeholder> :
null}
{props.children}</p>,
'underlined': props => <u {...props.attributes}>{props.children}</u>
},
marks: {
...
}
});
<Editor
state={this.state.state}
schema={Schema.Schema({this.props.placeholder})}
...
Closing this as the Placeholder component was removed in [email protected]
Most helpful comment
Thanks for @dmitrizzle 's example. But I think that it is a little bit obscure to know use
Placeholderin editor schema. And the propsparentandnodeare should not be cared by developers. Using in schema is more like customizing the content paragraph.Why not just give the customized component as prop
placeholder={<MyComponent />}? It might be easier for user to learn.