How can I make an entire row clickable in a DetailsList component? (office-ui-fabric) - office-ui-fabric

I've been using the DetailsList component but haven't found a way to make an entire row clickable - is there a sample code snippet or pointers on how this can be achieved?
https://developer.microsoft.com/en-us/fabric#/components/detailslist

Overriding onRenderRow worked for me.
const _columns: IColumn[] = [
{
key: 'name',
name: 'Name',
fieldName: 'name',
minWidth: 100,
maxWidth: 200,
isResizable: true
},
{
key: 'value',
name: 'Value',
fieldName: 'value',
minWidth: 100,
maxWidth: 200,
isResizable: true,
}
];
const _items = Array.apply(null, Array(10)).map((_: any, num: number) => ({
key: num.toString(),
name: `Item ${num.toString()}`,
value: num.toString()
}));
class Content extends React.Component {
private _renderRow(props: Fabric.IDetailsRowProps, defaultRender: any): JSX.Element {
return (
<Fabric.DetailsRow {...props} onClick={() => alert('click')}/>
);
}
public render() {
return (
<Fabric.Fabric>
<Fabric.DetailsList
items={ _items }
columns={ _columns.concat(..._columns, ..._columns, ..._columns) }
onRenderRow={this._renderRow}
/>
</Fabric.Fabric>
);
}
}
ReactDOM.render(
<Content />,
document.getElementById('content')
);

Here is th e single click solution,
Use onActiveItemChanged prop like:
const _onActiveItemChanged = (item): void => {
alert(`Item invoked: ${JSON.stringify(item)}`);
};
here is the DetailList
<DetailsList
items={assessmentList}
compact={false}
columns={columns}
onActiveItemChanged={_onActiveItemChanged }
/>

Please onItemInvoked Property and method. But it works on double click. I am also looking for single click solution
const onItemInvoked = (item): void => {
alert(`Item invoked: ${JSON.stringify(item)}`);
};
<DetailsList
items={assessmentList}
compact={false}
columns={columns}
selectionMode={SelectionMode.multiple}
getKey={_getKey}
setKey="multiple"
layoutMode={DetailsListLayoutMode.justified}
checkboxVisibility={CheckboxVisibility.hidden}
isHeaderVisible={true}
selectionPreservedOnEmptyClick={false}
enterModalSelectionOnTouch={true}
ariaLabelForSelectionColumn="Toggle selection"
ariaLabelForSelectAllCheckbox="Toggle selection for all items"
checkButtonAriaLabel="Select Checkbox"
onRenderRow={onRenderRow}
onItemInvoked={onItemInvoked}
onRenderDetailsHeader={(headerProps, defaultRender) => {
return (
<Sticky
stickyPosition={StickyPositionType.Header}
isScrollSynced={true}
stickyBackgroundColor="transparent"
>
<div className="text-center">{defaultRender(headerProps)}</div>
</Sticky>
);
}}
/>

Use onRenderRow and cloneElement to attach an onClick listener:
import React, { useCallback, cloneElement } from 'react';
import { DetailsList } from '#fluentui/react';
const Component = () => {
const onItemInvoked = useCallback( ( item ) => {
console.log( item );
}, [] );
const onRenderRow = useCallback( ( row, defaultRender ) => {
return cloneElement( defaultRender( row ), { onClick: () => onItemInvoked( row.item ) } )
}, [ onItemInvoked ] );
return (
<DetailsList
onRenderRow={ onRenderRow }
/>
);
};

Related

REACT NATIVE / my child component don't re-render despite props change

I'm facing an issue on the code below (sandbox here https://codesandbox.io/s/silly-rubin-9ghc5?fontsize=14&hidenavigation=1&theme=dark ), the props change but doesn't refresh the component accordingly.
I would like to be able to keep track of different votes / options within a state in the parent node, hence i'm using an array where the index is the index of my option and the value the number of votes.
import { useEffect, useState } from "react";
import { Button, View } from "react-native";
import "./styles.css";
const myList = [
{
cid: 0,
cTx: "Paris"
},
{
cid: 1,
cTx: "Lyon"
},
{
cid: 2,
cTx: "Marseille"
},
{
cid: 3,
cTx: "Valence"
},
{
cid: 4,
cTx: "Bordeaux"
}
];
interface mTprop {
myItemId: number;
myItemTxt: string;
myItemSt: number[];
myItemClck: () => void;
}
const MyItem = (props: mTprop) => {
const onBtPress = () => {
props.myItemClck();
console.log(props.myItemSt);
};
return (
<View
style={{
flexDirection: "row"
}}
>
<h3>{props.myItemTxt}</h3>
<Button onPress={onBtPress} title="Learn More" />
<h3>{props.myItemSt[props.myItemId]}</h3>
</View>
);
};
export default function App() {
const [selectedOpt, setSelectedOpts] = useState(new Array(0));
useEffect(() => {
setSelectedOpts(new Array(myList.length).fill(0));
}, []);
const updateOptions = (ix: number) => {
++selectedOpt[ix];
setSelectedOpts(selectedOpt);
};
return (
<div className="App">
<h1>Hello CodeSandbox</h1>
<h2>Start editing to see some magic happen!</h2>
{myList.map((itm, ix) => {
return (
<MyItem
key={ix}
myItemId={ix}
myItemTxt={itm.cTx}
myItemSt={selectedOpt}
myItemClck={() => updateOptions(ix)}
/>
);
})}
</div>
);
}
Thanks a million in advance !
Please let me know if further info is needed
In order to change data in list. You need to do this
const updateOptions = (ix: number) => {
const newList = selectedOpt.map((m, i) => {
if (i === ix) {
return m + 1;
}
return m;
});
setSelectedOpts(newList);
};

Can react-select underline searched text in filtered options?

I want to create react-select that when user type text, it will show filtered options whose part of match texts are underlined and change color from black to red as provided below image. Is it possible? Thanks.
After a while, I get the answer :)
import Select, { components } from 'react-select';
const options1 = [
{
value: 'chocolate',
label: 'chocolate',
},
{
value: 'strawberry',
label: 'strawberry',
},
{
value: 'vanilla',
label: 'vanilla'
}
]
class MyOption extends React.Component {
f_search = (input,option) => {
const num = option.indexOf(input)
const len = input.length
return (
<div>
<span>{option.substr(0, num)}</span>
<span style={{color:"red", textDecoration: "underline"}}>{input}</span>
<span>{option.substr(num +len)}</span>
</div>
)
}
render() {
const input = this.props.selectProps.inputValue
const option = this.props.data.label
return (
<components.Option {...this.props}>
{this.f_search(input,option)}
</components.Option>
)
}
}
const ReactSelect7 = () =>
<Select options={options1} components={{ Option: MyOption }} />

can anyone tell me ,how to use image in a flat-list of react-native?

class App extends Component {
constructor(props) {
super(props)
this.state = {
list: []
};
}
getList = () => {
const li = [
{ key: "image1", imagelink: "" },
{ key: "image2", imgLink: "imagelink" },
{ key: "image3", imgLink: "imagelink" },
{ key: "image3", imgLink: "imagelink" },
]
this.setState({
list: li
})
}
componentWillMount() {
this.getList()
}
render() {
return (
export default App;
You could just google it, but here is an example:
use FlatList for the list. Pass it the data and a render function.
<FlatList
data={this.data}
renderItem={({ item, index }) => this.renderItem(item, index)}
/>
then create the render function in your component:
renderItem(item, index) {
return (
<Image source={{uri: item.image}}/>
)
}
as an example the data is a component variable:
data = [{image: "link"}, {image: "link"}]

How to make dynamic checkbox in react native

I am making a react native application in which i need to make checkbox during runtime.I means that from server i will get the json object which will have id and label for checkbox.Now i want to know that after fetching data from server how can i make checkbox also how can i handle the checkbox , i mean that how many number of checkbox will be there it will not be static so how can i declare state variables which can handle the checkbox.Also how can i handle the onPress event of checkbox.Please provide me some help of code .Thanks in advance
The concept will be using an array in the state and setting the state array with the data you got from the service response, Checkbox is not available in both platforms so you will have to use react-native-elements. And you can use the map function to render the checkboxes from the array, and have an onPress to change the state accordingly. The code will be as below. You will have to think about maintaining the checked value in the state as well.
import React, { Component } from 'react';
import { View } from 'react-native';
import { CheckBox } from 'react-native-elements';
export default class Sample extends Component {
constructor(props) {
super(props);
this.state = {
data: [
{ id: 1, key: 'test1', checked: false },
{ id: 2, key: 'test1', checked: true }
]
};
}
onCheckChanged(id) {
const data = this.state.data;
const index = data.findIndex(x => x.id === id);
data[index].checked = !data[index].checked;
this.setState(data);
}
render() {
return (<View>
{
this.state.data.map((item,key) => <CheckBox title={item.key} key={key} checked={item.checked} onPress={()=>this.onCheckChanged(item.id)}/>)
}
</View>)
}
}
Here's an example how you can do this. You can play with the code, to understand more how it's working.
export default class App extends React.Component {
state = {
checkboxes: [],
};
async componentDidMount() {
// mocking a datafetch
setTimeout(() => {
// mock data
const data = [{ id: 1, label: 'first' }, { id: 2, label: 'second' }];
this.setState({
checkboxes: data.map(x => {
x['value'] = false;
return x;
}),
});
}, 1000);
}
render() {
return (
<View style={styles.container}>
<Text style={styles.paragraph}>
{JSON.stringify(this.state)}
</Text>
{this.state.checkboxes.length > 0 &&
this.state.checkboxes.map(checkbox => (
<View>
<Text>{checkbox.label}</Text>
<CheckBox
onValueChange={value =>
this.setState(state => {
const index = state.checkboxes.findIndex(
x => x.id === checkbox.id
);
return {
checkboxes: [
...state.checkboxes.slice(0, index),
{ id: checkbox.id, label: checkbox.label, value },
...state.checkboxes.slice(index+1),
],
};
})
}
value={checkbox.value}
key={checkbox.id}
/>
</View>
))}
</View>
);
}
}

Update position of All places in react-native-sortable-listview

I am using react-native-sortable-listview in react-native for sorting same places.
constructor() {
this.state = {
makers: [
{ kolkata: 'Hawrah Birdge' },
{ Delhi: 'Lal Kila' },
{ Agra: 'Taj Mahal' },
{ Mumbai: 'India Gate' },
],
allObj: {},
order: []
};
}
componentDidMount() {
const newAllObj = this.getAllObjFromMaker(this.state.makers);
const newOrder = this.getOrderFromMaker(newAllObj);
this.setState({ allObj: newAllObj, order: newOrder });
}
getAllObjFromMaker(makers) {
const allObj = makers.reduce((result, d) => {
result[`${d.coordinate.latitude}_${d.coordinate.longitude}`] = d;
return result;
}, {});
return allObj;
}
getOrderFromMaker(allObj) {
const order = Object.keys(allObj);
return order;
}
renderOneDraggableMilestone(milestone) {
const i = this.state.makers.indexOf(milestone);
return (
<TouchableOpacity {...this.props.sortHandlers}>
<Text>{i + 1}</Text>
<Text>{milestone.address}</Text>
</TouchableOpacity>
);
}
arrangedMilestoneList(e) {
const arr = this.state.makers;
arr.splice(e.to, 0, arr.splice(e.from, 1)[0]);
const newAllObj = this.getAllObjFromMaker(arr);
const newOrder = this.getOrderFromMaker(newAllObj);
this.setState({ makers: arr, allObj: newAllObj, order: newOrder
});
}
render() {
return (
<SortableListView
data={this.state.allObj}
order={this.state.order}
activeOpacity={0.5}
onRowMoved={e => {
this.arrangedMilestoneList(e);
this.forceUpdate();
}}
renderRow={(row) => this.renderOneDraggableMilestone(row)}
/>
);
}
I want to arrange places and also their position in this.state.makers as I am doing using i in renderOneDraggableMilestone. On renderRow only draggable place are render so only their position is updated. And renderRow is last to excute so forceUpdate is also not working.
How to rerender after executing renderRow. So all position could be updated.
Ok I have find a way to re-render as follow.
<SortableListView
key={this.state.count}
data={this.state.allObj}
order={this.state.order}
activeOpacity={0.5}
onRowMoved={e => {
this.setState({ count: this.state.count + 1 });
this.props.arrangedMilestoneList(e);
console.log('onRowMoved is called');
}}
onMoveEnd={() => console.log('onMoveEnd is fired')}
renderRow={(row, s1, i) => this.renderOneDraggableMilestone(row, s1, i)}
/>
What I am doing is I added a key attribute to SortableListView and update this key on each onRowMoved action. And because of this it causes re-render.