2017-01-18 9 views
8

У меня есть материал-UI's <Table>, и в каждом <TableRow> (который динамически отображается) для <TableBody>, я хотел бы иметь кнопку (<FlatButton>) для одного из столбцов. И как только кнопка нажата, она откроет <Dialog>, и внутри она хотела бы иметь рабочий <Tabs>.ReactJS + Material-UI: Как использовать Flat-UI FlatButton и Dialog в каждом TableRow?

Так как я могу отобразить <FlatButton> для каждой строки для конкретного столбца, а при нажатии на кнопку на отобразите <Dialog> вместе с рабочей <Tabs> на внутренней стороне, как содержание? И нажмите на кнопку <Dialog>, когда нажимаете на нее снаружи?

До сих пор у меня есть следующие, но наткнулся на следующие вопросы: открывает, но это медленно и щелчок вне <Dialog> не закрывая его, <Tabs> виден, но он не работает:

Главная Таблица:

import React, { Component } from 'react' 
import { 
    Subheader, 
    Table, 
    TableBody, 
    TableHeader, 
    TableHeaderColumn, 
    TableRow, 
} from 'material-ui' 

import RenderedTableRow from ‘./RenderedTableRow' 

export default class MainTable extends Component { 
    constructor() { 
    super() 
    } 

    render() { 

    return (
     <div> 
     <div> 
     <Subheader>Table</Subheader> 
      <Table 
      multiSelectable={true} 
      > 
      <TableHeader 
       displaySelectAll={true} 
       enableSelectAll={true} 
      > 
       <TableRow> 
       <TableHeaderColumn> 
        Col 1 
       </TableHeaderColumn> 
       <TableHeaderColumn> 
        Col 2 
       </TableHeaderColumn> 
       <TableHeaderColumn> 
        Col 3 
       </TableHeaderColumn> 
       </TableRow> 
      </TableHeader> 
      <TableBody 
       deselectOnClickaway={false} 
       stripedRows 
      > 
       <RenderedTableRow {...this.props}/> 
      </TableBody> 
      </Table> 
     </div> 
     </div> 
    ) 
    } 
} 

Вынесено строки таблицы:

import React, { Component } from 'react' 

import { Dialog, FlatButton, Tabs, Tab, TableRow, TableRowColumn } from 'material-ui' 
import ContentAdd from 'material-ui/svg-icons/content/add'; 

export default class RenderedTableRow extends Component { 
    constructor(props) { 
    super(props) 

    this.state = { 
     open: false, 
    } 

    this._handleOpen = this._handleOpen.bind(this) 
    this._handleClose = this._handleClose.bind(this) 
    } 

    _handleOpen() { 
    this.setState({ 
     open: true 
    }) 
    } 

    _handleClose() { 
    this.setState({ 
     open: false 
    }) 
    } 

    render() { 
    const { 
     children, 
     ...rest 
    } = this.props 

    const actions = [ 
     <FlatButton 
     label="Cancel" 
     primary={true} 
     onClick={this._handleClose} 
     />, 
    ] 

    return (
     <TableRow {...rest}> 
     {children[0]} 
     <TableRowColumn>Red</TableRowColumn> 
     <TableRowColumn>John, Joshua</TableRowColumn> 
     <TableRowColumn> 
      <FlatButton 
      icon={<ContentAdd/>} 
      onClick={this._handleOpen} 
      /> 
     </TableRowColumn> 

     <Dialog 
      actions={actions} 
      autoScrollBodyContent={true} 
      open={this.state.open} 
      onRequestClose={this._handleClose} 
      modal={false} 
      title='Test' 
     > 
      <Tabs> 
       <Tab label="Item One" > 
       <div> 
        <h2 >Tab One</h2> 
        <p> 
        This is an example tab. 
        </p> 
       </div> 
       </Tab> 

       <Tab label="Item Two" > 
       <div> 
        <h2>Tab Two</h2> 
        <p> 
        This is another example tab. 
        </p> 
       </div> 
       </Tab> 

      </Tabs> 
     </Dialog> 
     </TableRow> 
    ) 
    } 
} 

Спасибо заранее и будет принимать/upvote ответ.

+1

Что будет отображаться в диалоговом окне? Для каждой строки вы создаете новый диалог - это необходимо? Как вы упомянули, это будет очень медленно. Лучше всего использовать один элемент диалога в компоненте главной таблицы и передать необходимые реквизиты. – szymonm

+0

Я бы переместил диалог за пределы таблицы, передал обратный вызов кнопке в строке таблицы, которая нажимает, открывает диалог и передает выделенную ему строку – Mateusz

+0

@szymonm Разный контент для каждой строки, но он будет отображаться используя '' внутри диалогового окна, но в настоящее время вкладки не работают. Причина, почему я сделал это для каждой строки, состоит в том, что каждый диалог представлен по-разному для каждой строки. Как я могу обойти это? –

ответ

2

Возможно, у вас должен быть только один диалог для всей таблицы, который находится в вашем компоненте MainTable. Это более эффективно, потому что вам не нужно диалоговое окно для каждой строки, а только одно диалоговое окно.

Для того, чтобы кнопки в RenderedTableRow, чтобы открыть модальное и указать, какие строки выбраны вам нужно, чтобы передать функцию обратного вызова от MainTable к RenderedTableRow, что при вызове, устанавливает диалог, который будет открыт и магазинов, которые ряд был выбрано:

export default class MainTable extends Component { 
    state = { 
    selectedRow: null, 
    } 
    handleSelectRow(rowIndex) { 
    this.setState({ 
     selectedRow: rowIndex, 
    }) 
    } 
    render() { 

    return (
     <div> 
     <div> 
      <Subheader>Table</Subheader> 
      <Table 
      multiSelectable={true} 
      > 
      // ... 
      <TableBody 
       deselectOnClickaway={false} 
       stripedRows 
       > 
       {rows.map((row, index) => (
       <RenderedTableRow 
        row={row} 
        {...this.props} 
        onSelectRow={() => this.handleSelectRow(index)} 
        /> 
      ))} 
      </TableBody> 
      </Table> 
     </div> 
     // Dialog goes here and is only rendered once per table 
     // it is only open when there is a row selected 
     <Dialog 
      open={Boolean(this.state.selectedRow)} 
     > 
      // you can get the selected row with rows[this.state.selectedRow] 
     </Dialog> 
     </div> 
    ) 
    } 
} 
+0

Чтобы быть динамическими несколько строк, я буду заполняя таблицу массивом со специфическими свойствами для каждой строки следующим образом: ' {array.map (row => {return ()})};'. Если это так, как бы я различал, какие строка нажата и отображает этот конкретный контент внутри диалогового окна для этой конкретной строки, на которую нажата? Поскольку каждая строка будет отображать различный контент внутри диалогового окна. Также почему бы не «0»'работа? –

+0

Я расширил образец кода, чтобы включить несколько строк. Не уверен, почему 'Tabs' не будут работать. Они отлично смотрятся на меня. Я даже попробовал свой код «Dialog», и «Tabs» работал для меня. – PhilippSpo

+0

Вы не возражаете, показывая это с помощью кодекса или чего-нибудь подобного? Кажется, что не работает .. :( –

2

Ниже приведен рабочий пример ниже, он должен работать прямо через копировальную пасту.

Ответ на ваш вопрос заключается в том, что вы должны иметь возможность различать разные rows, установив его на true, чтобы отобразить все диалоги или, возможно, только последние. После того, как вы разделите его, отображение dialog, которое вы хотите, не должно быть проблемой. Есть способы просто иметь один dialog и все еще иметь эту работу, но я позволю вам понять это.

Признаки того, что вы можете определенно очистить этот код. Создайте отдельные файлы для создания TableRowsTableColumns и т. Д.

Я оставил его в двух столбцах на данный момент, однако вы должны понимать код. Не стесняйтесь задавать дополнительные вопросы.

import React, { Component } from 'react' 

import { Dialog, FlatButton, Tabs, Tab, TableRow, TableRowColumn } from 'material-ui' 
import ContentAdd from 'material-ui/svg-icons/content/add'; 

class MainTable extends Component { 
    static fields = [{tab1:"a", tab2:"b"}, {tab1:"c", tab2:"d"}]; 

    state = { 
    open: false, 
    } 

    handleOpen = (field) =>() => { 
    this.setState({ 
     open: field 
    }) 
    } 

    handleClose =() => { 
    this.setState({ 
     open: false 
    }) 
    } 

    renderRows = (field) => { 
    const { open } = this.state; 

    const actions = [ 
     <FlatButton 
     label="Cancel" 
     primary={true} 
     onTouchTap={this.handleClose} 
     />, 
     <FlatButton 
     label="Submit" 
     primary={true} 
     keyboardFocused={true} 
     onTouchTap={this.handleClose} 
     />, 
    ]; 

    return (<TableRow key={field.tab1}> 
     <TableRowColumn>{field.tab1}</TableRowColumn> 
     <TableRowColumn> 
     <FlatButton 
     icon={<ContentAdd/>} 
     onClick={this.handleOpen(field.tab1)} 
     /> 
     </TableRowColumn> 
     <Dialog 
      title="Dialog With Actions" 
      actions={actions} 
      modal={false} 
      open={open === field.tab1} 
      onRequestClose={this.handleClose} 
     > 
     <Tabs> 
      <Tab label={field.tab1} > 
      <div> 
       <h2>{field.tab1}</h2> 
       <p> 
       This is one tab. 
       </p> 
      </div> 
      </Tab> 

      <Tab label={field.tab2}> 
      <div> 
       <h2>{field.tab2}</h2> 
       <p> 
       This is another example tab. 
       </p> 
      </div> 
      </Tab> 
     </Tabs> 
     </Dialog> 
    </TableRow>); 
    } 

    render() { 
    const rows = MainTable.fields.map(this.renderRows); 
    return (
     <div> 
     {rows} 
     </div> 
    ) 
    } 
} 

export default MainTable; 
+0

Для динамических нескольких строк я буду заполнять таблицу массивом с конкретными свойствами для каждой строки следующим образом: {array.map (row => {return ()})};. Если это так, как бы я мог различать, на какую строку щелкнул, конкретный контент внутри диалога для этой конкретной строки, на который нажата? Поскольку каждая строка будет отображать различный контент внутри диалогового окна. Кроме того, почему бы не работать ? Если вы можете показать действительно рабочий, это действительно помогло бы. –

+0

I ' m на работе сейчас, но я обновлю ответ позже сегодня вечером, чтобы показать рабочие «вкладки». Я оставил эту часть. –

+0

Кстати, вы попробовали код выше? Нажав на различные «строки», вы увидите разную pes данных. Единственное, что я не рассматривал, это 'tabs', я не уверен, что они делают, но я могу проверить документы позже. –

1

Как я уже говорил ранее в комментариях, вы должны иметь только один Dialog элемент вместе с компонентом стола. Вложение Dialog в каждой строке будет влиять на производительность и является общей плохой практикой.Вот решение для издевался закладках:

import React, { Component } from 'react'; 
import { find } from 'lodash'; 
import { Dialog, FlatButton, Tabs, Tab, TableRow, TableRowColumn } from 'material-ui'; 
import ContentAdd from 'material-ui/svg-icons/content/add'; 

class MainTable extends Component { 
    // mocked data to show you the example: 
    static fields = [{ 
    id: 1, 
    name: 'John', 
    tabs: [{ 
     header: 'Tab 1 John', 
     content: 'Content of tab 1 for John' 
    }, { 
     header: 'Tab 2 John', 
     content: 'Content of tab 2 for John' 
    }] 
    }, { 
    id: 2, 
    name: 'George', 
    tabs: [{ 
     header: 'Tab 1 George', 
     content: 'Content of tab 1 for George' 
    }, { 
     header: 'Tab 2 George', 
     content: 'Content of tab 2 for George' 
    }] 
    }]; 

    state = { 
    activeRowId: null // we will store the `id` of the active row (opened dialog) 
    }; 

    handleOpen = (rowId) =>() => { 
    this.setState({ 
     activeRowId: rowId // set `id` taken from the row 
    }); 
    }; 

    handleClose =() => { 
    this.setState({ 
     activeRowId: null // reset active `id` 
    }); 
    }; 

    renderRows = (field) => (
    <TableRow key={`row-${field.id}`}> 
     <TableRowColumn>{field.name}</TableRowColumn> 
     <TableRowColumn> 
     <FlatButton 
      icon={<ContentAdd />} 
      onClick={this.handleOpen(field.id)} 
     /> 
     </TableRowColumn> 
    </TableRow> 
); 

    render() { 
    const rows = MainTable.fields.map(this.renderRows); 
    const { activeRowId } = this.state; 
    const actions = [ 
     <FlatButton 
     label="Cancel" 
     primary 
     onTouchTap={this.handleClose} 
     />, 
     <FlatButton 
     label="Submit" 
     primary 
     keyboardFocused 
     onTouchTap={this.handleClose} 
     />, 
    ]; 
    const activeRow = find(MainTable.fields, { id: activeRowId }); // find the data for this active row `id` 
    return (
     <div> 
     {rows} 
     {activeRow ? (
      <Dialog 
      title="Dialog title" 
      actions={actions} 
      modal={false} 
      open 
      onRequestClose={this.handleClose} 
      > 
      <Tabs> 
       {activeRow.tabs.map((tab, index) => (
       <Tab label={tab.header} key={`tab-${index}`}> 
        <div> 
        <h2>{tab.header}</h2> 
        <p>{tab.content}</p> 
        </div> 
       </Tab> 
      ))} 
      </Tabs> 
      </Dialog> 
     ) : null} 
     </div> 
    ); 
    } 
} 

export default MainTable; 

Вот как это работает прямо сейчас:

enter image description here

Несколько замечаний:

  • вы должны разделить этот код в меньшие компоненты, я написал это все в одном, чтобы было легко его протестировать,
  • не использовать key опору во всех элементах списка (где вы перебираете список) - в вашем вопросе отсутствует как строки, так и вкладки (key).