Umbro
Umbro

Reputation: 2204

Creating an editable inline textarea

Trying to create an editable inline textarea. When this.state.showTextAreaEdit isfalse I display

<span>
   <textarea> {todo.title} </ textarea>
   <button> Save </button>
</span>

otherwise, I display:

   

 <span>
   {todo.title}
   <button onClick={this.displayEdit}> Edit </button>
 </span>

Demo here: https://stackblitz.com/edit/react-yoevt8

The problem displays nothing. There are no errors in the console.

class App extends Component {
  constructor() {
    super();
    this.state = {
      todos: [],
      showTextAreaEdit: false
    };
  }

  componentDidMount() {
    this.getTodos();
  }

  displayEdit = () => {
    this.setState({
      showTextAreaEdit: true
    })
  }

  getTodos = () => {
    axios({
      url: 'https://jsonplaceholder.typicode.com/todos',
      method: 'GET'    
    })
      .then(res => {    
        this.setState({
          todos: res.data
        });
      })
      .catch(error => {
        console.log(error);
      });
  };

  render() {
    return (
      <ul>
        {this.state.todos.map((todo, index) => {
          return 
            <li key={todo.id}>
              {this.state.showTextAreaEdit ?
                <span>
                  <textarea>{todo.title}</textarea>
                  <button>Save</button>
                </span> 
                :
                <span>
                  {todo.title}
                  <button onClick={this.displayEdit}>Edit</button>
                </span>
              }
            </li>
        })}
      </ul>    
    );
  }
}

Upvotes: 1

Views: 97

Answers (4)

Ali Asgher Badshah
Ali Asgher Badshah

Reputation: 851

just replace your code with this one :-

what i did is that i took an new parameter on state which contain the id of selected list item and initially it is null when you click edit i pass the id on function and change its value to the id provided in the function.

and i also replace your condition. in this i check if the selected id matches the id of list item it show textarea field otherwise just simple text

import React, { Component } from 'react';
import { render } from 'react-dom';
import Hello from './Hello';
import './style.css';
import axios from 'axios';

class App extends Component {
  constructor() {
    super();
    this.state = {
      todos: [],
      showTextAreaEdit: false,
      editableTextArea:null
    };
  }

  componentDidMount() {
    this.getTodos();
  }

  displayEdit = (id) => {
    this.setState({
      editableTextArea: id
    })
  }

  getTodos = () => {
    axios({
      url: 'https://jsonplaceholder.typicode.com/todos',
      method: 'GET'    
    })
      .then(res => {    
        this.setState({
          todos: res.data
        });
      })
      .catch(error => {
        console.log(error);
      });
  };

  render() {
    return (
      <ul>
        {this.state.todos.map((todo, index) => {
        return   <li key={todo.id}>
              {this.state.editableTextArea == todo.id ?
                <span>
                  <textarea>{todo.title}</textarea>
                  <button>Save</button>
                </span> 
                :
                <span>
                  {todo.title}
                  <button onClick={()=>{this.displayEdit(todo.id)}}>Edit</button>
                </span>
              }
            </li>
        })}
      </ul>    
    );
  }
}

render(<App />, document.getElementById('root'));

it works great within your demo enjoy the code

Upvotes: 0

Imran
Imran

Reputation: 530

It's because the return statement doesn't find anything to return. Don't put enter after return statement. Try this

{this.state.todos.map((todo, index) => {
            return (<li key={todo.id}>
              {this.state.showTextAreaEdit ?
                <span>
                  <textarea>{todo.title}</textarea>
                  <button>Save</button>
                </span> 
                :
                <span>
                  {todo.title}
                  <button onClick={this.displayEdit}>Edit</button>
                </span>
              }
            </li>)
        })}

Upvotes: 1

Cjmarkham
Cjmarkham

Reputation: 9681

Since your return has multiple lines, you will need to wrap it in brackets:

{this.state.todos.map((todo, index) => {
  return ( // HERE
    <li key={todo.id}>
      {this.state.showTextAreaEdit ?
        <span>
          <textarea>{todo.title}</textarea>
          <button>Save</button>
        </span> 
      :
        <span>
          {todo.title}
          <button onClick={this.displayEdit}>Edit</button>
        </span>
      }
    </li>
  )
}

Upvotes: 1

Anh Tuan
Anh Tuan

Reputation: 1143

{this.state.todos.map((todo, index) =>
    <li key={todo.id}>
      {this.state.showTextAreaEdit ?
        <span>
          <textarea>{todo.title}</textarea>
          <button>Save</button>
        </span> 
        :
        <span>
          {todo.title}
          <button onClick={this.displayEdit}>Edit</button>
        </span>
      }
    </li>
)}

remove return in your map funtion at render

Upvotes: 0

Related Questions