2016-09-28 85 views
5

我無法在反應中顯示/隱藏某些元素。基本上,我有一個li的動態列表,在li中,我有一個標籤,當你點擊li時我想隱藏標籤並顯示一個輸入。通常用jQuery很容易,因爲如何在反應中動態顯示/隱藏項目列表

$('#element').hide() $('#element2').show()

我不太瞭解如何與我目前的佈局

class EntriesTable extends React.Component { 
 
    constructor(props) { 
 
     super(props); 
 

 
     console.log(this.props.plannerId); 
 
     this.state = { 
 
      tasks: [], 
 
      plannerId: this.props.plannerId, 
 
     }; 
 

 
     var state = this.state; 
 
    } 
 

 
    componentDidMount() { 
 
     this.getTasks(this.state.plannerId); 
 
    } 
 

 
    EditTask(id) { 
 
     console.log(id); 
 
     var spanEl = id + 'taskSpan'; 
 
     var inputEl = id + 'taskInput'; 
 
     //hide this span 
 
     //show input 
 
     $(spanEl).hide(); 
 
     $(inputEl).show(); 
 

 
     //when save 
 

 
     //hide input 
 
     //update task 
 
     //show span 
 
    } 
 

 
    updateTask(id, name) { 
 
     $.ajax({ 
 
      type: "GET", 
 
      url: "/Task/Update", 
 
      data: { id: id, name: name }, 
 
      contentType: "application/json; charset=utf-8", 
 
      success: function (data) { 
 
       console.log(data); 
 
       //this.setState({ tasks: data.ReturnObject, loading: false }); 
 
      }.bind(this), 
 
      error: function (xhr, status, err) { 
 
       console.log(err); 
 
      } 
 
     }); 
 
    } 
 

 
    createTask(name) { 
 
     //make api call to create planner here. 
 

 
     var data = { 
 
      Name: name, 
 
      PlannerId: model.plannerId, 
 
      Status: "Not Complete", 
 
      Description: "", 
 
      Affiliation: "", 
 
      Footprint: "", 
 
      Created: new Date(), 
 
      Modified: null, 
 
     }; 
 

 
     $.ajax({ 
 
      type: "POST", 
 
      url: "/Task/Add", 
 
      data: JSON.stringify(data), 
 
      contentType: "application/json; charset=utf-8", 
 
      success: function (data) { 
 
       console.log(data); 
 
       this.getTasks(model.plannerId); 
 
      }.bind(this), 
 
      error: function (xhr, status, err) { 
 
       console.log(err); 
 
      } 
 
     }); 
 
    } 
 

 
    getTasks(id) { 
 
     this.setState({ tasks: [], loading: true }); 
 
     $.ajax({ 
 
      type: "GET", 
 
      url: "/Task/GetAll", 
 
      data: { id: id }, 
 
      contentType: "application/json; charset=utf-8", 
 
      success: function (data) { 
 
       console.log(data); 
 
       this.setState({ tasks: data.ReturnObject, loading: false }); 
 
      }.bind(this), 
 
      error: function (xhr, status, err) { 
 
       console.log(err); 
 
      } 
 
     }); 
 
    } 
 

 
    render() { 
 
     const tasks = this.state.tasks.map((task) => { 
 
      var spanId = task.Id + "taskSpan"; 
 
      var inputId = task.Id + "taskInput"; 
 
      return (
 
       <li key={task.Id} className="list-group-item" style={{minHeight: '50px'}}> 
 
        <div className="pull-left" style={{width: '50%'}}> 
 
         <span id={spanId} onClick={this.EditTask.bind(this, task.Id) }>{task.Name}</span> 
 
         <input id={inputId} type="text" style={{ display: 'none' } } /> 
 
        </div> 
 
        <div className="pull-right" style={{marginTop: '-5px', width: '50%'}}> 
 
         <div className="pull-right"> 
 
          <button className="btn btn-default">Add</button> 
 
          <button className="btn btn-default">Edit</button> 
 
         </div> 
 
        </div> 
 
       </li> 
 
      ); 
 
     }); 
 
     return (
 
      <div className="table-wrapper"> 
 
      <div className="task-container"> 
 
       <h3>{this.props.rowName}</h3> 
 
      </div> 
 
      <ul id="tasksContainer"> 
 
       {tasks} 
 
       <li className="list-group-item list-group-item-last"><input type="button" value="Add Task" onClick={this.addTask.bind(this)} className="btn btn-success btn-override" /></li> 
 
      </ul> 
 
      </div> 
 

 
    ); 
 
    } 
 
};

實現這個我也看其他SO的,告訴你使用一個變量,然後通過改變變量來顯示/隱藏,但我不確定這是否適合我的需要,因爲我有一個動態列表,它不僅僅是一個單一的元素,我是tr要顯示或隱藏。

+0

你需要給我們正在呈現這個列表中的反應成分... – aray12

+0

我意思是說,我可以這樣做,但不確定它與問題的關係。我爲HTML的外觀提供了HTML代碼片段。我有一個跨度和輸入。我只想知道顯示/隱藏元素的首選反應方式。它只是通過jQuery來做,還是有什麼特別的反應? – jdmdevdotnet

+0

這是jsx不是html。而反應的方式是隱藏/顯示基於某些道具或狀態的東西。我們無法幫助您在沒有整個組件的情況下構建它 – aray12

回答

1

class EntriesTable extends React.Component { 
 
    constructor(props) { 
 
     super(props); 
 

 
     console.log(this.props.plannerId); 
 
     this.state = { 
 
      editableTasks: [], 
 
      tasks: [], 
 
      plannerId: this.props.plannerId, 
 
     }; 
 

 
     var state = this.state; 
 
     /* This isn't completely necessary but usually it is recommended you 
 
     * bind the class method in the constructor so it isn't bound on each 
 
     * render 
 
     */ 
 
     this.EditTask = this.EditTask.bind(this); 
 
    } 
 

 
    componentDidMount() { 
 
     this.getTasks(this.state.plannerId); 
 
    } 
 

 
    EditTask(id) { 
 
     /* So jQuery and react are kind of at odds with each other on fundamentals 
 
     * React is supposed to be declarative whereas jQuery is imperative. Using 
 
     * jQuery and React together is typically discouraged unless there is a real 
 
     * need for it. In React you are supposed to define how you want the UI to render 
 
     * based on some variables. You have two options available to you props and state. 
 
     * props are passed from the parent and are immutable. state is managed within that 
 
     * component and is mutable. So we have added a variable called editableTasks to your 
 
     * state that will contain an array of all editable tasks. Instead of trying to hide 
 
     * or show items here, we are simply going to add the id of now editable task to that 
 
     * array 
 
     * 
 
     */ 
 
     var nextState = this.state; 
 
     nextState.editableTasks.push(id); 
 
     this.setState(nextState); 
 
    } 
 

 
    updateTask(id, name) { 
 
     $.ajax({ 
 
      type: "GET", 
 
      url: "/Task/Update", 
 
      data: { id: id, name: name }, 
 
      contentType: "application/json; charset=utf-8", 
 
      success: function (data) { 
 
       console.log(data); 
 
       //this.setState({ tasks: data.ReturnObject, loading: false }); 
 
      }.bind(this), 
 
      error: function (xhr, status, err) { 
 
       console.log(err); 
 
      } 
 
     }); 
 
    } 
 

 
    createTask(name) { 
 
     //make api call to create planner here. 
 

 
     var data = { 
 
      Name: name, 
 
      PlannerId: model.plannerId, 
 
      Status: "Not Complete", 
 
      Description: "", 
 
      Affiliation: "", 
 
      Footprint: "", 
 
      Created: new Date(), 
 
      Modified: null, 
 
     }; 
 

 
     $.ajax({ 
 
      type: "POST", 
 
      url: "/Task/Add", 
 
      data: JSON.stringify(data), 
 
      contentType: "application/json; charset=utf-8", 
 
      success: function (data) { 
 
       console.log(data); 
 
       this.getTasks(model.plannerId); 
 
      }.bind(this), 
 
      error: function (xhr, status, err) { 
 
       console.log(err); 
 
      } 
 
     }); 
 
    } 
 

 
    getTasks(id) { 
 
     this.setState({ tasks: [], loading: true }); 
 
     $.ajax({ 
 
      type: "GET", 
 
      url: "/Task/GetAll", 
 
      data: { id: id }, 
 
      contentType: "application/json; charset=utf-8", 
 
      success: function (data) { 
 
       console.log(data); 
 
       this.setState({ tasks: data.ReturnObject, loading: false }); 
 
      }.bind(this), 
 
      error: function (xhr, status, err) { 
 
       console.log(err); 
 
      } 
 
     }); 
 
    } 
 

 
    render() { 
 
     const tasks = this.state.tasks.map((task) => { 
 
      var editable = this.state.editableTasks.filter(id => id === task.Id).length > 0; 
 
      /* Now here we are going to check whether this item is editable 
 
      * based on id. So we assign a variable that will eval to a bool 
 
      * based on whether when you filter editableTasks to see if it contains 
 
      * the current items id the length is greater than 0. 
 
      * 
 
      * Now below instead of applying some id attribute we are going to return either 
 
      * the input or the span based on whether it is editable using a ternary operation 
 
      * 
 
      */ 
 
      return (
 
       <li key={task.Id} className="list-group-item" style={{minHeight: '50px'}}> 
 
        <div className="pull-left" style={{width: '50%'}}> 
 
         {editable ? <input type="text" /> : <span onClick={this.EditTask(task.Id)}>{task.Name}</span>} 
 
         
 
        </div> 
 
        <div className="pull-right" style={{marginTop: '-5px', width: '50%'}}> 
 
         <div className="pull-right"> 
 
          <button className="btn btn-default">Add</button> 
 
          <button className="btn btn-default">Edit</button> 
 
         </div> 
 
        </div> 
 
       </li> 
 
      ); 
 
     }); 
 
     return (
 
      <div className="table-wrapper"> 
 
      <div className="task-container"> 
 
       <h3>{this.props.rowName}</h3> 
 
      </div> 
 
      <ul id="tasksContainer"> 
 
       {tasks} 
 
       <li className="list-group-item list-group-item-last"><input type="button" value="Add Task" onClick={this.addTask.bind(this)} className="btn btn-success btn-override" /></li> 
 
      </ul> 
 
      </div> 
 

 
    ); 
 
    } 
 
};

所以上面應該工作作出項目編輯。現在它不處理實際編輯它們或將它們返回到不可編輯狀態。但是這應該說明你應該如何完成這種'反應方式'。

我鼓勵你放棄jQuery。 jQuery將使你的React代碼更難以管理,並使其更難接受反應方式。如果你需要Ajax請求的東西,有很多小的庫也非常適合(強烈推薦使用superagent,但快速谷歌可以引導你到很多其他地方)

讓我知道如果你有任何其他問題。

1

要顯示動態顯示/隱藏在項目清單中的反應你的文件執行Visible.js:

import React, { Component } from 'react' 
import { Link, Router } from 'react-router'; 
import { connect } from 'react-redux'; 
import { Card, CardActions, CardHeader, CardMedia, CardTitle, CardText } from 'material-ui/Card'; 
import { List, ListItem } from 'material-ui/List'; 
import Divider from 'material-ui/Divider'; 
import '../../../static/images/cms-img3.jpg'; 
import '../../../static/images/cms-img4.jpg'; 
import '../../../static/images/cms-img5.jpg'; 
import '../../../static/images/grid-list/vegetables-790022_640.jpg'; 
import '../../../static/images/grid-list/00-52-29-429_640.jpg'; 
import '../../../static/images/grid-list/burger-827309_640.jpg'; 
import '../../../static/images/grid-list/camera-813814_640.jpg'; 
import '../../../static/images/grid-list/morning-819362_640.jpg'; 
import '../../../static/images/grid-list/hats-829509_640.jpg'; 
import '../../../static/images/grid-list/honey-823614_640.jpg'; 
import '../../../static/images/grid-list/water-plant-821293_640.jpg'; 
import '../../../static/images/video.mp4'; 
import '../../../static/images/video123.mp4'; 

class VisibleData extends Component { 
constructor(props) { 
    super(props); 
    this.state = { 
     items: [], 
    }; 
    this.onTodoClick = this.onTodoClick.bind(this); 
} 
componentDidMount() { 
    fetch('http://new.anasource.com/team9/news-api/?operation=view') 
     .then(result => result.json() 
      .then(news => { 
       this.setState({ items: news.news }); 
      }) 
     ); 
} 

componentWillMount() { 
    window.onpopstate = (event) => { 
     this.componentDidMount(); 
    }; 
} 

onTodoClick(id) { 
    this.setState({ 
     items: this.state.items.filter(item => item.news_id == id) 
    }); 
} 

render() { 
    return (
     <Data show={this.onTodoClick} items={this.state.items} /> 
    ) 
} 
} 

class Data extends Component { 

onTodoClick(e, id) { 
    this.props.show(id); 
} 

render() { 
    return ( 
     <div> 
      {this.props.items.map(item => { 
       const p = item.news_type == "image"; 
       const r = item.news_type == "video"; 
       return <Link to={"todo/#/" + item.news_id} key={item.news_id}> 
       <Card onClick={(e) => this.onTodoClick(e, item.news_id)} style={{margin:15}}> 
        <CardTitle title={item.news_title} subtitle={item.news_description}> 
         <CardMedia> 
          {p 
          ? <img src={item.news_src_url} /> 
          : null 
          } 
         </CardMedia> 
         <CardMedia> 
          {r 
          ? <video controls><source src={item.news_src_url} type="video/mp4"/></video> 
          : null 
          } 
         </CardMedia> 
         <div className='date'>{item.news_created_date}</div> 
        </CardTitle> 
       </Card> 
       </Link> 
      }) 
      } 
     </div> 
    ) 
} 
} 

export default VisibleData;