Slate: Any example for using Placeholder component?

Created on 14 Jul 2017  Â·  4Comments  Â·  Source: ianstormtaylor/slate

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. : )

examples ♥ help

Most helpful comment

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.

All 4 comments

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]

Was this page helpful?
0 / 5 - 0 ratings

Related issues

YurkaninRyan picture YurkaninRyan  Â·  3Comments

bengotow picture bengotow  Â·  3Comments

adrianclay picture adrianclay  Â·  3Comments

JSH3R0 picture JSH3R0  Â·  3Comments

bunterWolf picture bunterWolf  Â·  3Comments