简体   繁体   English

如何使数组可编辑

[英]How to make an array editable

I want to make the lists inside the ul editable. 我想让ul里面的列表可以编辑。 But I have no idea how to do it. 但我不知道该怎么做。 I have the delete functionality working but not editing. 我有删除功能,但没有编辑。 It works as so at the moment. 它目前的工作原理如此。 I write something into the input and it adds it to the list and by clicking it deletes, but I need an edit function to it. 我在输入中写了一些内容并将其添加到列表中并通过单击它删除,但我需要一个编辑功能。

This is a simple to-do list I'm working on 这是我正在制作的一个简单的待办事项清单

**TodoItems.js**
import React, { Component } from 'react';

class TodoItems extends Component {
    constructor(props) {
        super(props);
        this.createTasks = this.createTasks.bind(this);
    }
    createTasks(item) {
        return (
          <div>
            <li
              onClick={() => this.delete(item.key)}
              key={item.key}
            >
              {item.text}
            </li><p onClick={() => this.edit(item.key)}>Edit</p>
          </div>
        )
    }

    delete(key) {
        console.log("Key is: " + key);
        this.props.delete(key);
    }

    edit(key) {
        this.props.edit(key);
    }

    render() {
        var todoEntries = this.props.entries;
        var listItems = todoEntries.map(this.createTasks)

        return (
            <ul className="theList">
                {listItems}
            </ul>
        )
    }
}

TodoList.js TodoList.js

export default TodoItems;

import React, {Component } from 'react';
import TodoItems from './TodoItems';

class TodoList extends Component {
    constructor(props) {
        super(props);

        this.state = {
            items: []
        };
        this.addItem = this.addItem.bind(this);
        this.deleteItem =  this.deleteItem.bind(this);
    }

    addItem(e) {
        if (this._inputElement.value !== "") {
            var newItem = {
                text: this._inputElement.value,
                key: Date.now()
            };

            this.setState((prevState) => {
                return {
                    items: prevState.items.concat(newItem)
                };
            });
        }

        this._inputElement.value = "";

        console.log(this.state.items);

        e.preventDefault();
    }

    deleteItem(key) {
        console.log("Key is deleteItem:" + key);
        console.log("Items at delete: " + this.state.items);
        var filteredItems = this.state.items.filter(function (item){
            return (item.key !== key)
        });

        this.setState({
            items: filteredItems
        });
    }

    editItem(key) {

    }

    render() {
        return (
            <div className="todoListMain" >
                <div className="header">
                    <form onSubmit={this.addItem}>
                        <input ref={(a) => this._inputElement = a}
                            placeholder="enter task">
                        </input>
                        <button type="submit">add</button>
                    </form>
                </div>
                <TodoItems entries={this.state.items}
                            delete={this.deleteItem}/>
            </div>
        )
    }
}

export default TodoList;

The problem can be solved by using the contentEditable Property of HTML elements. 通过使用HTML元素的contentEditable属性可以解决该问题。 It also requires two buttons Edit/Done and a delete button. 它还需要两个按钮编辑/完成和一个删除按钮。 When Edit is selected the list item becomes editable and changes can be made. 选择“编辑”后,列表项将变为可编辑状态,并且可以进行更改。 Upon clicking on done the changes are saved in the state items. 单击完成后,更改将保存在状态项中。

class TodoItems extends Component {
constructor(props) {
super(props);
this.createTasks = this.createTasks.bind(this);
this.state = {showEditButton:true}
}
createTasks(item) {
   return 
   <div><li key={item.key}  contentEditable={item.editable}> {item.text} </li>
     <p onClick={() => this.delete(item.key)}>Delete</p>
      {this.state.showEditButton?<p onClick={() => this.edit(item.key)}>Edit</p>:<p onClick={() => this.done(item.key)}>Done</p>}
   </div>
   }

delete(key) {
console.log("Key is: " + key);
this.props.delete(key);
}

edit(key) {
this.props.edit(key);
this.setState({showEditButton:false})
}
done(key){
this.props.done(key);
this.setState({showEditButton:true})
}

render() {
var todoEntries = this.props.entries;
var listItems = todoEntries.map(this.createTasks)

return (
    <ul className="theList">
        {listItems}
    </ul>
 )
 }
}

The TodoList component is altered as follows TodoList组件改变如下

class TodoList extends Component {
 constructor(props) {
 super(props);
 this.state = {
    items: []
  };
this.addItem = this.addItem.bind(this);
this.deleteItem =  this.deleteItem.bind(this);
this.editItem = this.editItem.bind(this);
this.doneItem = this.doneItem.bind(this);
}

addItem(e) {
  if (this._inputElement.value !== "") {
    var newItem = {
        text: this._inputElement.value,
        key: Date.now(),
        editable:false
    };

    this.setState((prevState) => {
        return {
            items: prevState.items.concat(newItem)
        };
    });
 }

this._inputElement.value = "";

console.log(this.state.items);

e.preventDefault();
}

deleteItem(key) {
var filteredItems = this.state.items.filter(function (item){
    return (item.key !== key)
});

 this.setState({
    items: filteredItems
});
}

editItem(key) {

 var itemsCopy = this.state.items;
 itemsCopy.map(h=>{if(h.key==key)h.editable=true})
 this.setState({items:itemsCopy})
}
doneItem(key){

var itemsCopy = this.state.items;
itemsCopy.map(h=>{if(h.key==key)h.editable=false})
this.setState({items:itemsCopy})
}

render() {
return (
    <div className="todoListMain" >
        <div className="header">
            <form onSubmit={this.addItem}>
                <input ref={(a) => this._inputElement = a}
                    placeholder="enter task">
                </input>
                <button type="submit">add</button>
            </form>
        </div>
        <TodoItems entries={this.state.items}
           delete={this.deleteItem} edit={this.editItem} done={this.doneItem}/>
    </div>
   )
 }
}

You should add another one component, lets call it TodoItem , so you could manage state individually in every item. 你应该添加另一个组件,让我们称之为TodoItem ,这样你就可以在每个项目中单独管理状态。 Add couple of events to handle input change when editing name, and that's all. 在编辑名称时添加几个事件来处理输入更改,这就是全部。

Also it is not recommended that one of your props is called key , because it's used by React.js internally for detecting if one of element in collection were being changed. 此外,不建议您的某个props被称为key ,因为React.js在内部使用它来检测集合中的某个元素是否被更改。

Also div elements are not allowed as child of ul so I advice you to replace ul with div . div元素也不允许作为ul子元素,所以我建议你用div替换ul

Example

 let Component = React.Component; // New component class TodoItem extends Component { constructor(props) { super(props); this.state = { editMode: false } } onClickEdit = () => { this.setState({ editMode: true }) } onSubmit = (e) => { e.preventDefault(); let value = this.refs.input.value; this.props.edit(this.props.id, value); this.setState({editMode: false}) } render(){ let props = this.props; return ( <div> {!this.state.editMode && <span onClick={() => this.props.delete(props.id)}>{props.text}</span>} {this.state.editMode && <form onSubmit={this.onSubmit}> <input type='text' ref='input' defaultValue={props.text} /> </form>} <p onClick={this.onClickEdit}>Edit</p> </div> ) } } class TodoItems extends Component { constructor(props) { super(props); this.createTasks = this.createTasks.bind(this); this.state = { editMode: false } } createTasks(item) { return <TodoItem key={item.id} {...item} edit={this.edit} delete={this.delete}/>; } delete = (key) => { console.log("Key is: " + key); this.props.delete(key); } edit = (key, newValue) => { this.props.edit(key, newValue) } render() { var todoEntries = this.props.entries; var listItems = todoEntries.map(this.createTasks) return ( <div className="theList"> {listItems} </div> ) } } class TodoList extends Component { constructor(props) { super(props); this.state = { items: [] }; this.addItem = this.addItem.bind(this); this.deleteItem = this.deleteItem.bind(this); } addItem(e) { if (this._inputElement.value !== "") { var newItem = { text: this._inputElement.value, id: Date.now() }; this.setState((prevState) => { return { items: prevState.items.concat(newItem) }; }); } this._inputElement.value = ""; console.log(this.state.items); e.preventDefault(); } deleteItem(key) { console.log("Key is deleteItem:" + key); console.log("Items at delete: " + this.state.items); var filteredItems = this.state.items.filter(function (item){ return (item.id !== key) }); this.setState({ items: filteredItems }); } editItem = (id, newValue) => { let newItems = [].concat(this.state.items); let item = newItems.find(i=>i.id == id); item.text = newValue; this.setState({items: newItems}); } render() { return ( <div className="todoListMain" > <div className="header"> <form onSubmit={this.addItem}> <input ref={(a) => this._inputElement = a} placeholder="enter task"> </input> <button type="submit">add</button> </form> </div> <TodoItems entries={this.state.items} edit={this.editItem} delete={this.deleteItem}/> </div> ) } } ReactDOM.render(<TodoList />, document.querySelector('#app')) 
 <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script> <div id="app"></div> 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM