mcamac / react-text-annotate

React components for interactively highlighting parts of text.
https://mcamac.github.io/react-text-annotate
MIT License
134 stars 52 forks source link

how to set default value of tag and value based on an input from an another app #33

Closed munivinayk closed 3 years ago

munivinayk commented 3 years ago

In my below code. I have set initial state values (tag and value under public state) to empty. As per your code, these values currently changes based on the react select option (handlechange and handletagchange class) . But, i am also getting some input values from an upstream streamlit app and i want to use these values to set the initial values of state i.e for 'value' :(init_value) and 'tag' :(firsttag) - (please refer to variables after public render). Then later i want to change these default change based on the selection from the react select (handle change and handle tag change). Can some one help how to do that?

import {
  Streamlit,
  StreamlitComponentBase,
  withStreamlitConnection,
} from "streamlit-component-lib"
import React, { ReactNode } from "react"
import {TokenAnnotator, TextAnnotator} from 'react-text-annotate'
//import _ from 'lodash'
//import { Label } from 'semantic-ui-react'

const Card = ({children}:any) => (
  <div
    style={{
      boxShadow: '0 2px 4px rgba(0,0,0,.1)',
      margin: 6,
      maxWidth: 500,
      padding: 16,
    }}
  >
    {children}
  </div>
)

/**
 * This is a React-based component template. The `render()` function is called
 * automatically when your component should be re-rendered.
 */

class NlpAnnotate extends StreamlitComponentBase {

  public state = {value: [], tag: ''}

  handleChange = (value:any) => {
    this.setState({value})
  }

  handleTagChange = (e:any) => {
    this.setState({tag: e.target.value})
  }

  public render = (): ReactNode => {

    const TEXT = this.props.args["text"]
    const options = this.props.args["options"]
    const init_value:any = []
    var first = options[0]
    const firsttag = first.value

    const TAG_COLORS:any = {};
    for (var i = 0; i < options.length; i++) {TAG_COLORS[options[i].label] = options[i].color;}

    return (
        <div style={{padding: 24, fontFamily: 'IBM Plex Sans'}}>
        <div style={{display: 'flex', flexDirection: 'column', marginBottom: 24}}>
          <Card>
            <h4>Text for annotation</h4>
            <select onChange={this.handleTagChange} value={this.state.tag}>
                {options.map((option:any) => (
                <option value={option.value}>{option.label}</option>
                ))}
            </select>
            <TextAnnotator
              style={{
                fontFamily: 'IBM Plex Sans',
                maxWidth: 500,
                lineHeight: 1.5,
              }}
              content={TEXT}
              value={this.state.value}
              onChange={this.handleChange}
              getSpan={(span:any) => ({
                ...span,
                tag: this.state.tag,
                color: TAG_COLORS[this.state.tag],
              })}
            />
          </Card>
        </div>

        <Card>
          <h4>Json String</h4>
          <pre>{JSON.stringify({TEXT},null,2)}</pre>
          <pre>{JSON.stringify(this.state.value, null, 2)}</pre>
        </Card>
        <button
            onClick={() => Streamlit.setComponentValue(JSON.stringify(this.state.value, null, 2))}
        >
        save
        </button>
      </div>
    )
  }
}

// "withStreamlitConnection" is a wrapper function. It bootstraps the
// connection between your component and the Streamlit app, and handles
// passing arguments from Python -> Component.
//
// You don't need to edit withStreamlitConnection (but you're welcome to!).
export default withStreamlitConnection(NlpAnnotate)
munivinayk commented 3 years ago

I resolved it by changing the public state as below: public state = {value: this.props.args["init_value"], tag: this.props.args.options?.[0]?.value}