2014-02-05 30 views
30

我有一個小問題,而試圖創建一個選擇和取消選擇其他個人複選框複選框管理狀態(選擇/取消全部)配有React。我讀過http://facebook.github.io/react/docs/forms.html,發現有「控制」和「不可控」 <input> S之間的差異。我的測試代碼如下:陣營(臉譜):受控複選框

var Test = React.createClass({ 
    getInitialState: function() { 
     return { 
      data: [ 
       { id: 1, selected: false }, 
       { id: 2, selected: false }, 
       { id: 3, selected: false }, 
       { id: 4, selected: false } 
      ] 
     }; 
    }, 
    render: function() { 
     var checks = this.state.data.map(function(d) { 
      return (
       <div> 
        <input type="checkbox" data-id={d.id} checked={d.selected} onChange={this.__changeSelection} /> 
        {d.id} 
        <br /> 
       </div> 
      ); 
     }); 
     return (
      <form> 
       <input type="checkbox" ref="globalSelector" onChange={this.__changeAllChecks} />Global selector 
       <br /> 
       {checks} 
      </form> 
     ); 
    }, 
    __changeSelection: function(e) { 
     var id = e.target.getAttribute('data-id'); 
     var state = this.state.data.map(function(d) { 
      return { 
       id: d.id, 
       selected: (d.id === id ? !d.selected : d.selected) 
      }; 
     }); 

     this.setState({ data: state }); 

    }, 
    __changeAllChecks: function(e) { 
     var value = this.refs.globalSelector.getDOMNode().checked; 
     var state = this.state.data.map(function(d) { 
      return { id: d.id, selected: value }; 
     }); 

     this.setState({ data: state }); 
    } 
}); 

React.renderComponent(<Test />, document.getElementById('content')); 

「全局選擇」按預期工作:選擇時,選擇了其他所有檢查。問題在於__changeSelection()處理程序在單擊其他複選框之一時未觸發。

我不知道是什麼使這項工作的正確方法。也許React模型並不是模擬這種互動的最佳模型?我能做什麼?

在此先感謝

回答

42

在你render功能,thischecks映射功能範圍不同render,這是你需要__changeSelection範圍,所以this.__changeSelection不會找到一個__changeSelection屬性。如果添加一個.bind(this)到映射函數的最後,你可以綁定它的範圍相同thisrender

var checks = this.state.data.map(function(d) { 
    return (
     <div> 
      <input type="checkbox" data-id={d.id} checked={d.selected} onChange={this.__changeSelection} /> 
      {d.id} 
      <br /> 
     </div> 
    ); 
}.bind(this)); 

在一個側面說明,我只想通過id給處理函數,而不是分配數據屬性。這將刪除需要定位在處理程序元素:

var checks = this.state.data.map(function(d) { 
    return (
     <div> 
      <input type="checkbox" checked={d.selected} onChange={this.__changeSelection.bind(this, d.id)} /> 
      {d.id} 
      <br /> 
     </div> 
    ); 
}.bind(this)); 

然後更新您的__changeSelection功能在id傳遞作爲第一個參數,並刪除該屬性查找行:

__changeSelection: function(id) { 
    var state = this.state.data.map(function(d) { 
     return { 
      id: d.id, 
      selected: (d.id === id ? !d.selected : d.selected) 
     }; 
    }); 

    this.setState({ data: state }); 

} 

這裏這一切的例子放在一起,along with a jsfiddle for you to try it out

/** @jsx React.DOM */ 

var Test = React.createClass({ 
    getInitialState: function() { 
     return { 
      data: [ 
       { id: 1, selected: false }, 
       { id: 2, selected: false }, 
       { id: 3, selected: false }, 
       { id: 4, selected: false } 
      ] 
     }; 
    }, 
    render: function() { 
     var checks = this.state.data.map(function(d) { 
      return (
       <div> 
        <input type="checkbox" checked={d.selected} onChange={this.__changeSelection.bind(this, d.id)} /> 
        {d.id} 
        <br /> 
       </div> 
      ); 
     }.bind(this)); 
     return (
      <form> 
       <input type="checkbox" ref="globalSelector" onChange={this.__changeAllChecks} />Global selector 
       <br /> 
       {checks} 
      </form> 
     ); 
    }, 
    __changeSelection: function(id) { 
     var state = this.state.data.map(function(d) { 
      return { 
       id: d.id, 
       selected: (d.id === id ? !d.selected : d.selected) 
      }; 
     }); 

     this.setState({ data: state }); 

    }, 
    __changeAllChecks: function() { 
     var value = this.refs.globalSelector.getDOMNode().checked; 
     var state = this.state.data.map(function(d) { 
      return { id: d.id, selected: value }; 
     }); 

     this.setState({ data: state }); 
    } 
}); 

React.renderComponent(<Test />, document.getElementById('content')); 
+1

謝謝,這解決了這個問題。我完全忘了'這個'綁定。既然我們正在討論綁定,爲什麼使用這個.__ changeSelection.bind(this,d.id)而不是這個.__ changeSelection(id)?我承認這個「綁定」對我來說是新事物(現在我正在學習React)。 –

+7

@馬修斯 - EMM使用'這.__ changeSelection(ID)'會立即調用該函數(例如渲染時)。我們只是想傳遞函數的引用,以便可以在'onChange'事件後面調用它。例如,如果你輸入'console。日誌「在你的瀏覽器控制檯中,它會打印出這個函數,但是如果你鍵入'console.log()'它會觸發實際的函數。 'anyFunc.bind(this,arg)'會創建一個綁定到'this'的新函數,並將所有傳入原函數的參數前置,但不會調用它。 –

+0

我正在嘗試使用'checked:@ props.checkAll'來設置複選框的狀態,它按預期工作。但是,設置此屬性後,我無法手動檢查/取消選中。刪除這個屬性後,我可以手動執行 – vipin8169

3

如果你正在處理的複選框就可以使用checkedLink屬性。這裏是另一個可能的實現,使得(在目前的答案,而不是不加控制)控制的全球複選框:

JsFiddle

var Test = React.createClass({ 

    getInitialState: function() { 
     return { 
      globalCheckbox: false, 
      data: [ 
       { id: 1, selected: false }, 
       { id: 2, selected: false }, 
       { id: 3, selected: false }, 
       { id: 4, selected: false } 
      ] 
     }; 
    }, 

    changeCheckForId: function(id,bool) { 
     this.setState(
      { 
      data: this.state.data.map(function(d) { 
       var newSelected = (d.id === id ? bool : d.selected); 
       return {id: d.id, selected: newSelected}; 
      } 
     )}); 
    }, 

    changeCheckForAll: function(bool) { 
     this.setState({ 
       globalCheckbox: true, 
       data: this.state.data.map(function(d) { 
        return {id: d.id, selected: bool}; 
       }) 
     }); 
    }, 



    linkCheckbox: function(d) { 
     return { 
     value: d.selected, 
     requestChange: function(bool) { this.changeCheckForId(d.id,bool); }.bind(this) 
     }; 
    }, 

    linkGlobalCheckbox: function() { 
     return { 
     value: this.state.globalCheckbox, 
     requestChange: function(bool) { this.changeCheckForAll(bool); }.bind(this) 
     }; 
    }, 

    render: function() { 
     var checks = this.state.data.map(function(d) { 
      return (
       <div> 
        <input key={d.id} type="checkbox" checkedLink={this.linkCheckbox(d)} /> 
        {d.id} 
        <br /> 
       </div> 
      ); 
     }.bind(this)); 

     return (
      <form> 
       <input type="checkbox" checkedLink={this.linkGlobalCheckbox()} />Global selector 
       <br /> 
       {checks} 
      </form> 
     ); 
    }, 

}); 

它更容易使用checkedLink=this.linkState("checkboxValue")LinkedStateMixin如果發生變異狀態不深嵌套(象是這這個問題的情況下)

編輯checkedLinkvalueLink被棄用,但在作出反應的早期版本中recommmended。

+0

我試圖使用'checked:@ props.checkAll來設置複選框的狀態',正在按預期工作。但是,設置此屬性後,我無法手動檢查/取消選中。刪除此屬性後,我可以手動執行 – vipin8169

+0

'checkedLink'似乎根本不起作用。儘管設置了'checkedLink = true'我看不到複選框被選中 – vipin8169

+0

@ vipin8169我從來沒有說過使用checkedLink = true請仔細閱讀m'y答案checkedLink屬性需要一個包含2個屬性的對象 –