Text formating with CSS - css

I am using the ant-design library with the Table and Tooltip component
I am trying to format the tooltip so that each element inside of my array is on it's own line instead of 1 big paragraph like how it is here.
The code that generates the above UI looks like this
const generateTableColumns = () => {
if (survey) {
const selectedSurvey = `${survey}`.toLowerCase()
const columnHeaders = SurveyArray[selectedSurvey].questions.map(item => ({
title: item.id,
dataIndex: item.id,
key: item.id,
ellipsis: {
showTitle: false,
},
render: dataIndex => (
<Tooltip placement="topLeft" title={dataIndex}>
{dataIndex}
</Tooltip>
),
}))
setTableColumns(columnHeaders)
}
}
I have tried doing
render: dataIndex => (
<Tooltip placement="topLeft" title={dataIndex}>
{ {_.isArray(dataIndex) ? dataIndex.map(item => <p className="test">{item}</p>) : null} }
</Tooltip>
),
Which formats the elements in the table, not the tooltip.
Does anyone have any idea on how I can style the elements inside of the span like I did on the table?

I believe you need to use "\n" to break line.
"Hi, my name is Emir." => "Hi, my name is Emir."
"Hi, \n my name is Emir." =>
"Hi,
my name is Emir."
Note: I'm not sure about the answer I wish I could add this as a comment but my reputation is not enough to comment. Have a nice day!

render: dataIndex => (
<Tooltip
placement="topLeft"
title={
_.isArray(dataIndex) ? dataIndex.map(item => <p className="test">{item}</p>) : null
}
>
{dataIndex}
</Tooltip>
),
From reading the docs, looks like title is what is being used to render the elements inside of the tooltip. This gave me what I was after

Related

How To scroll to the last message in the react virtualization message container

I am using scrollToIndex and scrollToRow but is not working on adding a new message, Also I tried with use ref but was not able to make it work, feel free to suggest. In your text, I would be more than happy to receive.
I want to scroll to the last message when we add a new message.
useEffect(() => {
parentRef.current!?.lastElementChild?.scrollIntoView()
}, [messagesList])
const rowRenderer = useCallback(
({index, isScrolling, key, parent, style, scrollToRow}) => {
const chat = messagesList[index]
console.log(
'cell renderer index : ',
index,
' list length : ',
messagesList.length
)
return (
<CellMeasurer
cache={cache}
columnIndex={0}
key={key}
parent={parent}
rowIndex={index}
className='List'
scrollToRow={messagesList.length - 1}
autoHeight={true}
autoWidth={true}
// ref={parentRef}
recomputeRowHeights={index}
recomputeRowWidths={index}
resetMeasurementForRow={index}
resetMeasurementForColumn={index}
resetMeasurements={true}
style={{wordWrap: 'break-word', whiteSpace: 'normal', flexWrap: 'wrap'}}>
{({measure, registerChild}: any) => (
<div style={style}>
<Message
key={chat?.id}
ref={registerChild}
data={chat}
/>
</div>
)}
</CellMeasurer>
)
},
[messagesList, cache]
)
const getMessages = useMemo(() => {
console.log('getting messages....')
return (
<List
scrollToAlignment={'end'}
height={700}
width={wrapperRef.current ? wrapperRef.current?.clientWidth : 100}
style={{width: '100%', border: '2px solid grey'}} // important to maintain the width
itemSize={10}
deferredMeasurementCache={cache}
rowHeight={cache.rowHeight}
rowCount={messagesList.length}
rowRenderer={rowRenderer}
// scrollToIndex={messagesList.length}
// ref={parentRef}
scrollToRow={messagesList.length - 1}
// scrollToIndex
/>
)
}, [messagesList, wrapperRef.current])
scrollToIndex={messagesList.length - 1} works fine here and this solved my issue

React-Table display contents of array as individual elements inside a cell

I am trying to use react-table to visualise some data structured as below:
{
companyName: "Barclays Bank Plc",
tenancies: ["G.01 # Newbuilding"],
status: "Active",
accountNumber: "EX209302",
logo: "companylogo1",
},
{
companyName: "Boeing AerospaceLtd",
tenancies: ["G.01 # Newbuilding", "G.02 # Newbuilding"],
status: "Active",
accountNumber: "EX209302",
logo: "companylogo1",
},
My column definition (which doesn't work) looks something like this:
{
Header: "Tenancies",
accessor: "tenancies",
Cell: (tableProps) => (
<div>{tableProps.cell.value.forEach((item) => item)}</div>
),
},
What I am trying to do is display each array item within it's own HTML tags (such as a div) so I can visually style and seperate them within the table cell.
Can anyone point me in the right direction as to the best way to achieve this?
According to the API document, the Cell receives the table Instance and returns a valid JSX.
{
...
Cell: (tableInstance) => JSX
}
Since the tenancies array are available from tableInstance.row.original.tenancies, so you can change your tenancies column definition as follow:
{
Header: "Tenancies",
Cell: ({ row }) => {
return (
<div>
{row.original.tenancies.map((tenancy, i) => (
<div key={i}>{tenancy}</div>
))}
</div>
);
}
}
Here is the example:

Material-UI DataGrid: How do I add a tooltip to each row cell?

I could not find anything related to this in the react material ui datagrid documentation here. I noticed you can add tooltips to columns via a "description" field, but can not find any documentation or examples related to rows.
modify columns to add renderCell attribute
const columns: Columns = [
{
field: 'id',
headerName: 'ID',
sortable: false,
renderCell: (params: any) => (
<Tooltip title={params.data.id} >
<span className="table-cell-trucate">{params.data.id}</span>
</Tooltip>
),
}
]
css changes :
.table-cell-trucate {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
I modified the columns like this:
const editColumns = columns.map((column) => ({
field: column,
headerName: column,
width:75,
flex: 1,
renderCell: (params: any) => (
<Tooltip title={params.value}>
<span>{params.value}</span>
</Tooltip>
),
}));
Just debug your code on rendercell and check what data you are getting in params, according to that filter your code.
renderCell: (params) => (
<Tooltip title={params.value} >
<span className="csutable-cell-trucate">{params.value}</span>
</Tooltip>
),
this worked for me.
You might want to use the GridCellParams type if you use TypeScript:
renderCell: (params: GridCellParams) => (
<Tooltip title={params.value}>
<span className="table-cell-trucate">{params.value}</span>
</Tooltip>
)

react-table : Add a select (checkboxes) column with a headergroup

For aesthetic reasons I'm trying to add a HeaderGroup to the "select" (checkboxes) column solution provided in react-teable examples.
hooks => {
hooks.visibleColumns.push(columns => {
return [
{
id: 'selection',
// Make this column a groupByBoundary. This ensures that groupBy columns
// are placed after it
groupByBoundary: true,
// The header can use the table's getToggleAllRowsSelectedProps method
// to render a checkbox
Header: ({ getToggleAllRowsSelectedProps }) => (
<div>
<IndeterminateCheckbox {...getToggleAllRowsSelectedProps()} />
</div>
),
// The cell can use the individual row's getToggleRowSelectedProps method
// to the render a checkbox
Cell: ({ row }) => (
<div>
<IndeterminateCheckbox {...row.getToggleRowSelectedProps()} />
</div>
),
},
...columns,
]
})
Source:
https://codesandbox.io/s/github/tannerlinsley/react-table/tree/master/examples/kitchen-sink
I've tried many ways using hooks object but none of them worked (for example nested calls to hooks.headerGroups.push and then hooks.visibleColumns.push).
Here is my last attempt which makes sense but doesn't work either (TypeError: Cannot read property 'forEach' of undefined) :
hooks => {
hooks.headerGroups.push(headerGroups => {
return [
{
Header: 'X',
columns: [
{
id: 'selection',
// Make this column a groupByBoundary. This ensures that groupBy columns
// are placed after it
groupByBoundary: true,
// The header can use the table's getToggleAllRowsSelectedProps method
// to render a checkbox
Header: ({ getToggleAllRowsSelectedProps }) => (
<div>
<IndeterminateCheckbox {...getToggleAllRowsSelectedProps()} />
</div>
),
// The cell can use the individual row's getToggleRowSelectedProps method
// to the render a checkbox
Cell: ({ row }) => (
<div>
<IndeterminateCheckbox {...row.getToggleRowSelectedProps()} />
</div>
),
}
]
},
...headerGroups
]
})
})
Thank you for your help ^^

Wordpress Gutenberg autocomplete - saving attributes

I want to develop a custom block that will let the user pick some information from autocomplete. I manage to create the autocomplete component on edit function.
A user can select an item but i don't know how to handle the attribute save.
I'm trying to save the selected item as attribute package_name. I created the onChange function on Autocomplete component but event.target.value is undefined.
Here is my code from block.js
const { __ } = wp.i18n; // Import __() from wp.i18n
const { AlignmentToolbar,
BlockControls,
registerBlockType } = wp.blocks;
const { RichText } = wp.editor;
const { Autocomplete, } =wp.components;
const MyAutocomplete = () => {
const autocompleters = [
{
name: 'fruit',
triggerPrefix: '#',
options: [
{ name: 'Apple', id: 1 },
{ name: 'Orange', id: 2 },
{ name: 'Grapes', id: 3 },
{ name: 'test', id: 4 },
],
getOptionLabel: option => (
<span>
{ option.name }
</span>
),
getOptionKeywords: option => [ option.name ],
isOptionDisabled: option => option.name === 'Grapes',
getOptionCompletion: option => (
<abbr title={ option.name }>{ option.name }</abbr>
),
}
];
function onChangeAuto(newContent){
console.log('autocompletexx '+newContent);
}
function onSelectAuto(event){
console.log(event.target);
console.log( event.target.value);
}
return (
<div>
<Autocomplete completers={ autocompleters }>
{ ( { isExpanded, listBoxId, activeId } ) => (
<div
contentEditable
suppressContentEditableWarning
aria-autocomplete="list"
aria-expanded={ isExpanded }
aria-owns={ listBoxId }
aria-activedescendant={ activeId }
onChange={onChangeAuto }
onSelect={onSelectAuto}
>
</div>
) }
</Autocomplete>
<p class="autocomplete_p">Type # for triggering the autocomplete.</p>
</div>
);
};
registerBlockType( 'residence-gutenberg-block/membership-package-settings', {
title: __( 'Residence - Membership Package Settings' ), // Block title.
icon: 'shield',
category: 'common',
keywords: [
__( 'membership-package-settings' ),
],
attributes:{
package_id:{
type:'string',
select:'p'
},
package_name:{
type:'string',
},
},
edit: function( props ) {
const { attributes: {package_name}, className,setAttributes,isSelected } = props;
return (
<div className={ props.className }>
<form>
<label className="wpresidence_editor_label">Current Package: {package_name}</label>
<MyAutocomplete></MyAutocomplete>
</form>
</div>
);
},
save: function( props ) {
// Rendering in PHP
return null;
},
} );
Passing down onChange, onSelect to the div element won't work, because these attributes are only applicable to the form field elements (as input, select, etc.).
I checked the documentation and the source code and didn't find any details or official approaches for dealing with the case.
However, I'm seeing two possible approaches for getting the selected value:
1. Using Autocomplete onReplace prop
Looking into the Autocomplete's source code, I noticed that onSelect callback invokes onReplace prop with the selected option as array. It may not fit all the cases, but you can give it a try! It may be enough for your case! You can try to add your handler to the onReplace as follows:
<Autocomplete
onReplace={ option => { console.log(option) } }
completers={ autocompleters }>
{ ( { isExpanded, listBoxId, activeId } ) => (
<div
contentEditable
suppressContentEditableWarning
aria-autocomplete="list"
aria-expanded={ isExpanded }
aria-owns={ listBoxId }
aria-activedescendant={ activeId }
/>
) }
</Autocomplete>
2. Listen for <div /> changes manually
You can add onInput, onBlur listeners to the <div />, having an uncontrolled react div component and when the div's value is changed then we can keep the changed value in your parent component's state.
Here's a great discussion, which describes these technique: React.js: onChange event for contentEditable
The good think is that there's already a plugin (based on this discussion) that can do it for you: react-contenteditable.
Firstly you have to convert your <MyAutocomplete /> component to be a statefull (not functional) and then:
import ContentEditable from 'react-contenteditable'
// Boilerplate ...
<Autocomplete completers={ autocompleters }>
{ ( { isExpanded, listBoxId, activeId } ) => (
<ContentEditable
html={this.state.html}
onChange={this.handleChange}
contentEditable
suppressContentEditableWarning
aria-autocomplete="list"
aria-expanded={ isExpanded }
aria-owns={ listBoxId }
aria-activedescendant={ activeId }
/>
) }
</Autocomplete>
Conclusion
I'm surprised that in the Autocomplete's documentation there aren't any details for this case. I guess it's because of the following statement (27.08.2018):
Gutenberg is being developed on GitHub, and you can try an early beta
version today from the plugin repository. Though keep in mind it’s not
fully functional, feature complete, or production ready.
However, one of both mentioned approaches above will help you, until they provide a complete API to work with their components.
I would suggest you to keep wrapping the Wordpress's <Autocomplete /> with your own component - in order to easily refactor your code later, when they release the complete API.
If you have questions, feel free to comment below.

Resources