2017-01-18 2 views
8

Ich habe eine Material UI <Table>, und in jedem <TableRow> (die dynamisch wiedergegeben wird) für die <TableBody>, würde Ich mag, einen Knopf haben (<FlatButton>) für eine der Spalten. Und sobald der Knopf angeklickt ist, öffnet sich ein <Dialog> und im Inneren wäre ein funktionierender <Tabs>.ReactJS + Material-UI: Wie werden FlatButton und Dialog von Material-UI in jedem TableRow verwendet?

So wie kann ich zeige ein <FlatButton> für jede Zeile für eine bestimmte Spalte, und wenn die Taste angeklickt wird, zeigen Sie die <Dialog> zusammen mit einem Arbeits <Tabs> auf der Innenseite als Inhalt? Und lassen Sie die <Dialog> schließen, wenn Sie draußen geklickt haben?

Bisher habe ich die folgende haben, kam aber über die folgenden Themen: das eröffnet, aber es ist langsam und klicken außerhalb des <Dialog> schließt es nicht, die <Tabs> ist sichtbar, aber es funktioniert nicht:

Haupt Tabelle:

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> 
    ) 
    } 
} 

Rendered Tabellenzeile:

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> 
    ) 
    } 
} 

Vielen Dank im Voraus und akzeptiert/upvote Antwort.

+1

Was wird im Dialog angezeigt? Für jede Zeile generieren Sie einen neuen Dialog - ist das notwendig? Wie du bereits erwähnt hast, wird es sehr langsam sein. Besserer Ansatz ist es, ein Dialog-Element in der Haupttabelle zu haben und die notwendigen Requisiten zu übergeben. – szymonm

+0

Ich würde den Dialog außerhalb der Tabelle verschieben, einen Callback an eine Schaltfläche in der Tabellenzeile übergeben, die beim Klicken öffnet, öffnet Dialog und übergibt die ausgewählte Zeile daran – Mateusz

+0

@szymonm Unterschiedlicher Inhalt für jede Zeile, aber es wird angezeigt von Verwenden '' '' innerhalb des Dialogs, aber zur Zeit funktionieren die Tabs nicht. Der Grund, warum ich es für jede Zeile gemacht habe, liegt darin, dass jeder Dialog für jede Zeile unterschiedlich dargestellt wird. Wie kann ich das umgehen? –

Antwort

2

Sie sollten wahrscheinlich nur einen Dialog für die gesamte Tabelle haben, der in Ihrer MainTable Komponente lebt. Dies ist effizienter, da Sie keinen Dialog pro Zeile, sondern nur einen Dialog benötigen.

Damit die Schaltfläche in der RenderedTableRow den Modal öffnen und sagen, welche Zeile ausgewählt ist Sie eine Rückruffunktion MainTable-RenderedTableRow zu überliefern müssen, dass, wenn sie aufgerufen, setzt den Dialog geöffnet und speichert werden, die Reihe war ausgewählt:

+0

Damit es mehrere dynamische Reihen gibt, werde ich sein Füllen der Tabelle mit einem Array mit spezifischen Eigenschaften für jede Zeile wie folgt: ' {array.map (row => {return ()})};'. Wenn das der Fall ist, wie würde ich unterscheiden, welche Zeile wurde angeklickt und zeigt an, dass ein bestimmter Inhalt in einem Dialog für diese bestimmte Zeile angeklickt wurde? Weil jede Zeile einen anderen Inhalt in einem Dialog anzeigt. Auch warum nicht die ' 'Arbeit? –

+0

Ich habe das Codebeispiel um mehrere Zeilen erweitert. Nicht sicher, warum die 'Tabs' nicht funktionieren würden. Sie sehen gut aus für mich. Ich habe sogar deinen 'Dialog'-Code ausprobiert und die' Tabs' funktionieren für mich. – PhilippSpo

+0

stört es, es mit Codepen oder ähnliches zu zeigen? Scheint nicht zu funktionieren .. :( –

2

Hier ist ein Arbeitsbeispiel unten, sollte es direkt über Kopie Pasta funktionieren.

Die Antwort auf Ihre Frage ist, dass Sie in der Lage sein müssen, zwischen den verschiedenen rows unterscheiden, setzen Sie es auf true wird alle Dialoge angezeigt, oder möglicherweise nur die letzte. Sobald Sie es unterscheiden, sollte die Anzeige der dialog Sie wollen kein Problem sein. Es gibt Möglichkeiten, nur eine dialog zu haben und immer noch diese Arbeit zu haben, aber ich lasse dich herausfinden.

Etwas zu beachten, ist, dass Sie diesen Code auf jeden Fall reinigen können. Erstellen Sie separate Dateien zum Erstellen TableRowsTableColumns usw.

Ich habe es für jetzt auf zwei Spalten verlassen, aber Sie sollten in der Lage sein, den Code zu verstehen. Fühlen Sie sich frei, irgendwelche zusätzlichen Fragen zu stellen.

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

Damit es mehrere dynamische Zeilen gibt, werde ich die Tabelle mit einem Array füllen mit spezifischen Eigenschaften für jede Zeile wie folgt: {array.map (row => {return ()})};. Wenn das der Fall ist, wie würde ich unterscheiden, auf welche Zeile geklickt wurde und das anzeigen bestimmter Inhalt in einem Dialog für diese bestimmte Zeile angeklickt? Weil jede Zeile anderen Inhalt innerhalb eines Dialogs anzeigt. Auch warum funktioniert die nicht? Wenn Sie wirklich arbeiten können, würde das wirklich helfen. –

+0

I ' Ich arbeite jetzt, aber ich werde später die Antwort aktualisieren, um die Funktion "Tabs" zu zeigen. Ich habe diesen Teil weggelassen. –

+0

Übrigens, hast du den obigen Code ausprobiert? Wenn du auf die verschiedenen Zeilen klickst, werden die verschiedenen Symbole angezeigt Daten. Das einzige, was ich nicht untersucht habe, sind "Tabs", ich bin mir nicht sicher, was sie tun, aber ich kann die Dokumente später überprüfen. –

1

Wie ich in den Kommentaren bereits erwähnt, sollten Sie nur eine Dialog Element zusammen mit der Tabellenkomponente haben. Einbetten Dialog in jeder Zeile wird die Leistung beeinträchtigen und ist allgemein eine schlechte Praxis.Hier ist die Lösung für verspottet Registerkarten:

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; 

Dies ist, wie es jetzt funktioniert:

enter image description here

Ein paar Bemerkungen:

  • Sie diesen Code spalten sollte in kleinere Komponenten, schrieb ich das alles in einem, um es einfach zu testen,
  • Denken Sie daran, key Stütze in allen Elementen der Liste zu verwenden (wo Sie über eine Liste iterieren) - beide Zeilen und Tabs (key fehlt in Ihrer Frage).
Verwandte Themen