Using a sidebar component from [office-ui-fabric-react][1].
I want to sidebar to start in the Collapsed state, but I am having difficulty setting the state of the ISidebar interface to do this.
How can I toggleCollapsed on this imported component?
export interface ISidebar {
/**
* Toggles the sidebar state to put the sidebar in or out of collapsed mode
* #type {(boolean) => void}
*/
toggleCollapsed: () => void;
}
export class SidebarExample extends React.Component {
public render(): JSX.Element {
this.state = {
active: true
};
return (
<Sidebar
id={'sidebar-collapsed'}
collapsible={true}
theme={getTheme()}
/>
)
Public methods (e.g. toggleCollapsed) of Sidebar component are accessible through componentRef, for example:
<Sidebar componentRef={initSidebar} />
const initSidebar = (sideBar: ISidebar) => {
sideBar.toggleCollapsed();
};
Example
The initial collapsed state could be set like this:
const initSidebar = (ref: ISidebar) => {
ref.setCollapsed(true);
};
const SidebarBasicExample: React.SFC<{}> = props => {
return (
<Sidebar
componentRef={initSidebar}
collapsible={true}
id={"1"}
theme={getTheme()}
items={[
{
key: "basic-example-item1",
name: "Item 1",
iconProps: { iconName: "BuildQueue" },
active: false
},
{
key: "basic-example-item2",
name: "Item 2",
iconProps: { iconName: "Bullseye" },
active: true
}
]}
/>
);
};
With Vadim's help, my answer.
import { getTheme } from 'office-ui-fabric-react';
import * as React from 'react';
import { Sidebar, ISidebar } from '#uifabric/experiments/lib/Sidebar';
const initSidebar = (sideBar: ISidebar) => {
sideBar.toggleCollapsed();
};
export class SidebarCollapsibleExample extends React.Component {
public render(): JSX.Element {
this.state = {
active: true
};
return (
<Sidebar
id={'sidebar-collapsed'}
collapsible={true}
theme={getTheme()}
collapseButtonAriaLabel={'sitemap'}
componentRef={initSidebar}
items={[
{
key: 'collapsible-example-item1',
name: 'Item 1',
iconProps: { iconName: 'BuildQueue' },
active: false
} ]}
/>
);
}
}
Related
I made a example in following:
I am new to React and i am using React Select
import React, { Component, Fragment } from "react";
import Select from 'react-select';
const options = [
{ value: 'blues', label: 'Blues' },
{ value: 'rock', label: 'Rock' },
{ value: 'jazz', label: 'Jazz' },
{ value: 'orchestra', label: 'Orchestra' }
];
class DropDown3 extends Component {
constructor(props){
super(props)
this.state = {
selectOptions : [],
id: "",
name: ''
}
}
handleChange = (selectedOption) =>
{
console.log("selected",selectedOption)
this.setState({ selectedOption });
};
render()
{
const { selectedOption } = this.state;
return (
<Fragment>
<Select
options = {options}
onChange ={this.handleChange}
value = {selectedOption}
defaultValue={{ value: 'jazz', label: 'Jazz' }}
/>
<div>Hello you select {this.state.selectedOption}</div>
</Fragment>
);
}
}
export default DropDown3;
what i want is to display what i have selected in the dropdown so that i can pass it to another component.
The abouve code didnt run everytime i choose a menu
and it run only i comment out the
"Hello you select {this.state.selectedOption}"
thanks
You should initialize the selectedOption in the state, and when you update the state you should take the value of the selectedOption object.
import React, { Component, Fragment } from "react";
import Select from "react-select";
const options = [
{ value: "blues", label: "Blues" },
{ value: "rock", label: "Rock" },
{ value: "jazz", label: "Jazz" },
{ value: "orchestra", label: "Orchestra" }
];
class DropDown3 extends Component {
constructor(props) {
super(props);
this.state = {
selectOptions: [],
selectedOption: "",
id: "",
name: ""
};
}
handleChange = (selectedOption) => {
console.log("selected", selectedOption);
this.setState({ selectedOption: selectedOption.value });
};
render() {
const { selectedOption } = this.state;
return (
<Fragment>
<Select
options={options}
onChange={this.handleChange}
value={selectedOption}
defaultValue={{ value: "jazz", label: "Jazz" }}
/>
<div>Hello you select {this.state.selectedOption}</div>
</Fragment>
);
}
}
export default DropDown3;
I am trying to implement a feature where in on click of each row, I need to get the info of the row that is been clicked and corresponding row color should be changed to something else. And when I select multiple rows using Ctrl+mouse-click the corresponding rows color should also get changed, and need to get the info of corresponding rows in the form of array. I need to have a common getTrProps function that should implement both of this . Can someone help me out with this
Codesandbox: https://codesandbox.io/s/react-table-row-table-0bbyi
App
import * as React from "react";
import { render } from "react-dom";
import DataGrid from "./DataGrid";
import { Column } from "react-table";
interface IProps {}
interface IState {
data: IUser[];
columns: Column<IUser>[];
}
export interface IUser {
firstName: string;
status: "Submitted" | "Pending" | "Approved";
age: string;
}
export interface IColum {
Header: string;
accessor: string;
}
class App extends React.Component<IProps, IState> {
constructor(props: IProps) {
super(props);
this.state = {
data: [],
columns: []
};
}
componentDidMount() {
this.getData();
this.getColumns();
}
getData = () => {
const data: IUser[] = [
{ firstName: "Jack", status: "Submitted", age: "14" },
{ firstName: "Simon", status: "Pending", age: "15" },
{ firstName: "Pete", status: "Approved", age: "17" }
];
this.setState({ data });
};
getColumns = () => {
const columns: IColum[] = [
{
Header: "First Name",
accessor: "firstName"
},
{
Header: "Status",
accessor: "status"
},
{
Header: "Age",
accessor: "age"
}
];
this.setState({ columns });
};
onClickRow = (rowInfo: IUser) => {
console.log("You clicked: " + JSON.stringify(rowInfo));
};
render() {
return (
<>
<DataGrid
data={this.state.data}
columns={this.state.columns}
rowClicked={this.onClickRow}
/>
<DataGrid data={this.state.data} columns={this.state.columns} />
</>
);
}
}
DataGrid
import * as React from "react";
import ReactTable, {
RowInfo,
Column,
ComponentPropsGetterR
} from "react-table";
import "react-table/react-table.css";
import { IUser, IColum } from ".";
interface IProps {
data: IUser[];
columns: Column<IUser>[];
// The ? makes it optional
rowClicked?: (user: IUser) => void;
}
export default class DataGrid extends React.Component<IProps> {
rowClick: ComponentPropsGetterR = (state: any, rowInfo: RowInfo) => {
const rowClicked = this.props.rowClicked;
return rowClicked
? {
onClick: () => rowClicked(rowInfo.original as IUser)
}
: {};
};
render() {
return (
<ReactTable
data={this.props.data}
columns={this.props.columns}
getTrProps={this.rowClick}
/>
);
}
}
Here is Your Final Answer :
https://codesandbox.io/s/react-table-row-table-3xwxi
you can now hold Ctrl Key and Select as many row as you want and you can toggle between.
and if you don't hold the key you can select one
you can see each time you choose a row color of the row Changes.
and you have all the data in this.state.allData.
and all of this in typescript as you want from your sandbox.
I have 2 components (a form for inputing values and a react-table component to display the inputed values) that I am putting on a dashboard. When I enter the values into the form to update the redux store, I can see the changes from redux tools however, the table component doesn't update until I go to a different page and come back. Anyone know what I am doing wrong?
Here is my reducer. I don't believe I am mutating the state here.
Reducer:
const keysReducerDefaultState = [];
export default (state = keysReducerDefaultState, action) => {
switch (action.type) {
case 'ADD_KEYS':
return [
...state,
action.keyPair
];
case 'REMOVE_KEYS':
return state.filter(({ name }) => {
return name !== action.name;
});
default:
return state;
}
}
Component 1
class KeysImportForm extends React.Component {
constructor(props) {
super(props);
this.state = {
// type validation
name: "",
publicKey: "",
privateKey: "",
};
this.typeClick = this.typeClick.bind(this);
}
render() {
const { classes } = this.props;
return (
// a form that takes in 3 fields, name, publickey and privatekey
);
}
}
const mapDispatchToProps = (dispatch) => ({
addKeys: (keyPair) => dispatch(addKeys(keyPair))
});
export default withStyles(validationFormsStyle)(connect(undefined, mapDispatchToProps)(KeysImportForm));
Component 2
class KeysTable extends React.Component {
constructor(props) {
super(props);
const data = props.keys.map((prop, key) => {
return {
id: key,
name: prop.name,
publicKey: prop.publicKey,
privateKey: prop.privateKey,
};
});
this.state = {
data
};
}
render() {
const { classes } = this.props;
return (
<GridContainer>
<GridItem xs={12}>
<Card>
<CardHeader color="primary" icon>
<CardIcon color="primary">
<Assignment />
</CardIcon>
<h4 className={classes.cardIconTitle}>Key Pairs</h4>
</CardHeader>
<CardBody>
<ReactTable
data={this.state.data}
filterable
columns={[
{
Header: "Name",
accessor: "name",
minWidth: 10
},
{
Header: "Public Key",
accessor: "publicKey",
minWidth: 50
},
{
Header: "Private Key",
accessor: "privateKey",
minWidth: 50
},
{
Header: "Action",
accessor: "action",
minWidth: 10,
sortable: false,
filterable: false
}
]}
defaultPageSize={10}
showPaginationTop
showPaginationBottom={false}
className="-striped -highlight"
/>
</CardBody>
</Card>
</GridItem>
</GridContainer>
);
}
}
const mapDispathToProps = (dispatch, props) => ({
removeKeys: (id) => dispatch(removeKeys(id))
});
const mapStateToProps = (state) => {
return {
keys: state.keys
}
}
export default withStyles(styles)(connect(mapStateToProps, mapDispathToProps)(KeysTable));
Dashboard
class Dashboard extends React.Component {
state = {
value: 0
};
handleChange = (event, value) => {
this.setState({ value });
};
handleChangeIndex = index => {
this.setState({ value: index });
};
render() {
const { classes } = this.props;
return (
<div>
<KeysImportForm/>
<KeysTable/>
</div>
);
}
}
Dashboard.propTypes = {
classes: PropTypes.object.isRequired
};
export default withStyles(dashboardStyle)(Dashboard);
I'm not 100% sure, but it looks like you are having the following error:
In your constructor you do a (unnecessary) copy of you props to your state, which introduces the error and defeats the purpose of Redux:
const data = props.keys.map((prop, key) => {
return {
id: key,
name: prop.name,
publicKey: prop.publicKey,
privateKey: prop.privateKey,
};
});
This causes your data to only update when your constructor is called, which is when your component mounts (a.k.a. you reload your page).
Instead use your props directly as your data. Redux will cause your component to re-render every time the state changes.
I'm trying to follow the example here from the office-ui-fabric-react repo simply to test the new focusedIndex function to scroll a selection into view.
However, WebStorm is highlighting a TS2322 error in the render() function trying to set the componentRef property to a class variable:
(short error)
TS2322: Type '{componentRef: RefObject... is not assignable to type 'IntrinsicAttributes & IntrinsicClassAttributes...
The error occurs when using the full unmodified code from the link, but here's a snippet of the relevant class code for reference and the ** affected line ** in the render() function:
import * as React from 'react';
import { BaseComponent } from 'office-ui-fabric-react/lib/Utilities';
import { DefaultButton } from 'office-ui-fabric-react/lib/Button';
import { Fabric } from 'office-ui-fabric-react/lib/Fabric';
import { IDetailsList, DetailsList, IColumn } from 'office-ui-fabric-react/lib/DetailsList';
import { Checkbox } from 'office-ui-fabric-react/lib/Checkbox';
import './DetailsList.Grouped.Example.scss';
export class DetailsListGroupedExample extends BaseComponent<
{},
{
items: {}[];
showItemIndexInView: boolean;
}
>
{
private _root = React.createRef<IDetailsList>();
constructor(props: {}) {
super(props);
this.state = {
items: _items,
showItemIndexInView: false
};
}
public render() {
const { items } = this.state;
return (
<Fabric className="DetailsList-grouped-example">
<div>
<Checkbox
label="Show index of the first item in view when unmounting"
checked={this.state.showItemIndexInView}
onChange={this._onShowItemIndexInViewChanged}
/>
</div>
<DefaultButton onClick={this._addItem} text="Add an item" />
<DetailsList
componentRef={this._root} //**TS2322 ERROR HERE**
items={items}
groups={[
{
key: 'groupred0',
name: 'By "red"',
startIndex: 0,
count: 2
},
{
key: 'groupgreen2',
name: 'By "green"',
startIndex: 2,
count: 0
},
{
key: 'groupblue2',
name: 'By "blue"',
startIndex: 2,
count: items.length - 2
}
]}
columns={_columns}
ariaLabelForSelectAllCheckbox="Toggle selection for all items"
ariaLabelForSelectionColumn="Toggle selection"
groupProps={{
showEmptyGroups: true
}}
onRenderItemColumn={this._onRenderColumn}
/>
</Fabric>
);
}
}
What am I doing wrong or what do I need to do to resolve this compile error?
So, on the example i've get rid of
private _root = React.createRef<IDetailsList>
and all of references to this object. Then example works like a charm.
It looks like something has been changed in fabric react controls, but codesamples on their website has not been updated which is annoying.
My code:
import * as React from 'react';
import styles from './RsfDictionaries.module.scss';
import { IRsfDictionariesProps } from './IRsfDictionariesProps';
import { escape } from '#microsoft/sp-lodash-subset';
import { TextField } from 'office-ui-fabric-react/lib/TextField';
import { Toggle } from 'office-ui-fabric-react/lib/Toggle';
import { DetailsList, DetailsListLayoutMode, Selection, SelectionMode, IColumn, IDetailsList } from 'office-ui-fabric-react/lib/DetailsList';
import { MarqueeSelection } from 'office-ui-fabric-react/lib/MarqueeSelection';
import { IDocument, IDetailsListDocumentsExampleState } from './states';
import { BaseComponent } from 'office-ui-fabric-react/lib/Utilities';
import { DefaultButton } from 'office-ui-fabric-react/lib/Button';
import { Fabric } from 'office-ui-fabric-react/lib/Fabric';
import { Checkbox } from 'office-ui-fabric-react/lib/Checkbox';
const _columns = [
{
key: 'name',
name: 'Name',
fieldName: 'name',
minWidth: 100,
maxWidth: 200,
isResizable: true
},
{
key: 'color',
name: 'Color',
fieldName: 'color',
minWidth: 100,
maxWidth: 200
}
];
const _items = [
{
key: 'a',
name: 'a',
color: 'red'
},
{
key: 'b',
name: 'b',
color: 'red'
},
{
key: 'c',
name: 'c',
color: 'blue'
},
{
key: 'd',
name: 'd',
color: 'blue'
},
{
key: 'e',
name: 'e',
color: 'blue'
}
];
export default class RsfDictionaries extends React.Component<IRsfDictionariesProps, {
items: {}[];
showItemIndexInView: boolean;
}> {
constructor(props: any) {
super(props);
this.state = {
items: _items,
showItemIndexInView: false
};
}
public componentWillUnmount() {
if (this.state.showItemIndexInView) {
const itemIndexInView = 0;//this._root!.current!.getStartItemIndexInView();
alert('unmounting, getting first item index that was in view: ' + itemIndexInView);
}
}
private _root :IDetailsList; //React.createRef<IDetailsList>();
public render(): React.ReactElement<IRsfDictionariesProps> {
const { items } = this.state;
return (
<Fabric className="DetailsList-grouped-example">
<div>
<Checkbox
label="Show index of the first item in view when unmounting"
checked={this.state.showItemIndexInView}
onChange={this._onShowItemIndexInViewChanged}
/>
</div>
<DefaultButton onClick={this._addItem} text="Add an item" />
<DetailsList
//={this._root}
items={items}
groups={[
{
key: 'groupred0',
name: 'By "red"',
startIndex: 0,
count: 2
},
{
key: 'groupgreen2',
name: 'By "green"',
startIndex: 2,
count: 0
},
{
key: 'groupblue2',
name: 'By "blue"',
startIndex: 2,
count: items.length - 2
}
]}
columns={_columns}
ariaLabelForSelectAllCheckbox="Toggle selection for all items"
ariaLabelForSelectionColumn="Toggle selection"
groupProps={{
showEmptyGroups: true
}}
onRenderItemColumn={this._onRenderColumn}
/>
</Fabric>
);
}
private _addItem = (): void => {
const items = this.state.items;
this.setState(
{
items: items.concat([
{
key: 'item-' + items.length,
name: 'New item ' + items.length,
color: 'blue'
}
])
},
() => {
//if (this._root.current) {
//this._root.current.focusIndex(items.length, true);
//}
}
);
};
private _onRenderColumn(item: any, index: number, column: IColumn) {
let value = item && column && column.fieldName ? item[column.fieldName] : '';
if (value === null || value === undefined) {
value = '';
}
return (
<div className={'grouped-example-column'} data-is-focusable={true}>
{value}
</div>
);
}
private _onShowItemIndexInViewChanged = (event: React.FormEvent<HTMLInputElement>, checked: boolean): void => {
this.setState({
showItemIndexInView: checked
});
};
}
I have a problem that my makeSelectable code is not working when I used the ListItem from child component instead of using ListItem directly. Here is my example code (the workingLinkItems can be selected normally but the notWorkingLinkItems is not selectable).
import React, { Component, PropTypes } from 'react'
import { List, makeSelectable, ListItem } from 'material-ui/List'
import { wrapState } from 'helpers/utils'
const { func, shape, string, number } = PropTypes
class TryListItem extends Component {
static propTypes = {
onOpenLink: func.isRequired,
linkItem: shape({
key: number.isRequired,
link: string.isRequired,
text: string.isRequired,
}).isRequired,
}
handleOpenLink = () => {
this.props.onOpenLink(this.props.linkItem.link)
}
render () {
const { key, link, text } = this.props.linkItem
return <ListItem
value={key}
primaryText={text}
onTouchTap={this.handleOpenLink} />
}
}
let SelectableList = makeSelectable(List)
SelectableList = wrapState(SelectableList)
class TrySelectableList extends Component {
handleOpenLink = (location) => {
console.log('The page will be redirected to: ', location)
}
render () {
const links = [
{
key: 1,
link: '/home',
text: 'Home',
},
{
key: 2,
link: '/about',
text: 'About Us',
},
{
key: 3,
link: '/contact',
text: 'Contact Us',
},
]
const notWorkingLinkItems = links.map((link) => (
<TryListItem
onOpenLink={this.handleOpenLink}
linkItem={link} />
))
const workingLinkItems = links.map((link) => (
<ListItem
value={link.key + 3}
primaryText={link.text}
onTouchTap={this.handleOpenLink} />
))
return (
<div>
<SelectableList defaultValue={1}>
{notWorkingLinkItems}
{workingLinkItems}
</SelectableList>
</div>
)
}
}
export default TrySelectableList
Any idea what's wrong with my code?
Finally after a lot of trial tinkering with material-ui makeSelectable function. I ended up creating my own selectable style.
Here is my code solution for my problem:
import React, { Component, PropTypes } from 'react'
import { List, ListItem } from 'material-ui/List'
const { bool, func, shape, string, number } = PropTypes
class TryListItem extends Component {
static propTypes = {
selected: bool.isRequired,
onOpenLink: func.isRequired,
linkItem: shape({
link: string.isRequired,
text: string.isRequired,
}).isRequired,
}
handleOpenLink = () => {
this.props.onOpenLink(this.props.linkItem.link, this.props.linkItem.key)
}
render () {
const { key, link, text } = this.props.linkItem
const styles = this.props.selected
? { backgroundColor: 'rgba(0, 0, 0, 0.2)', }
: {}
return <ListItem
primaryText={text}
onTouchTap={this.handleOpenLink}
style={styles} />
}
}
class TrySelectableList extends Component {
componentWillMount = () => {
this.buildLink()
}
buildLink = (selectedIndex = 0) => {
const initialLinks = [
{
key: 1,
link: '/home',
text: 'Home',
selected: false,
},
{
key: 2,
link: '/about',
text: 'About Us',
selected: false,
},
{
key: 3,
link: '/contact',
text: 'Contact Us',
selected: false,
},
]
const links = initialLinks.map((link) => {
if (link.key === selectedIndex) {
link.selected = true
}
return link
})
this.setState({
links: links
})
}
handleOpenLink = (location, index) => {
console.log('The page will be redirected to: ', location)
this.buildLink(index)
}
render () {
const workingLinkItems = this.state.links.map((link) => (
<TryListItem
key={link.key}
selected={link.selected}
onOpenLink={this.handleOpenLink}
linkItem={link} />
))
return (
<div>
<List>
{workingLinkItems}
</List>
</div>
)
}
}
export default TrySelectableList