I'm using react-bootstrap-table to display my data in table format. This is an excerpt from my current code:
var table = (
<BootstrapTable ref="table" data={convertedData} deleteRow={false} striped={true} search={false} pagination={true} hover={true} selectRow={selectRowProp}>
<TableHeaderColumn columnClassName="col-md-1" dataField="field1" isKey={true}>field1</TableHeaderColumn>
<TableHeaderColumn columnClassName="col-md-2" dataField="field2" >field2</TableHeaderColumn>
<TableHeaderColumn columnClassName="col-md-2" dataField="field3">field3</TableHeaderColumn>
</BootstrapTable>
);
}
return (
<div>
<h2>{this.props.title}</h2>
{table}
</div>
)
},
From my css file:
.table td.col-md-7 {
word-wrap: normal;
overflow: auto;
text-overflow: clip;
}
The issue I'm facing is that cells with a lot of text, gets a scrollbar when what I actually want is to display the text in multiple rows within the cell.
Any ideas on how to get this working?
Found an approach that seems ok:
function multilineCell(cell, row) {
return "<textarea class='form-control cell' rows='3'>" + cell +"</textarea>";
}
[...]
<TableHeaderColumn columnClassName="col-md-4" dataFormat={multilineCell} dataField="summary">Summary</TableHeaderColumn>
Related
I have two JSF elements (e.g., an input text, and an image). For some condition (e.g., if a user is logged in), I want the input text to be rendered first. For the opposite condition (e.g., the user is anonymous), I want the image to be rendered first. Is there a way to accomplish that (that can scale to more than just 2 elements)? The only idea I have, which looks hacky, is the following:
<h:inputText rendered=#{condition}/>
<h:graphicImage/>
<h:inputText rendered=#{!condition}/>
I would use CSS to solve this. Roughly it comes down to:
XHTML:
<div class="container input#{condition ? 'First' : 'Last'}">
<h:inputText/>
<h:graphicImage/>
</div>
CSS:
.container { overflow: auto; }
.container.inputFirst input { float: left; }
.container.inputLast input { float: right; }
Again, this is rough. It's just to give you an idea. Customize it to your needs. There are many ways in which you could style this.
If you want to use flex, try:
.container { display: flex; }
.container.inputLast { flex-direction: row-reverse; }
I use antd table in my project and often use a horizontal scroll when there are many columns in a table that cannot be displayed in a single frame. The width for each column is defined. It was working fine in previous days but now i am having a problem with column width. The column width is not working properly if i don't apply ellipsis to each column. Is there any way to fix it rather than using ellipsis separately for each column?
const tableColumns = () => {
return [
{
title: 'col one',
dataIndex: 'throws',
key: 'throws',
width:110,
ellipsis: true,
sorter: (a, b) => stringValueSort(a.throws, b.throws),
},
{
title: 'col two',
dataIndex: 'bats',
key: 'bats',
width:90,
ellipsis: true,
sorter: (a, b) => stringValueSort(a.bats, b.bats),
},
]
};
If i use ellipsis: true property columns width automatically adjust according to the text content in column. Width of the column still not been applied using this width property.
.antd-table-custom-class thead th, .antd-table-custom-class tbody td {
white-space:pre-wrap;
text-overflow: ellipsis
}
if you want to see whole text please
.antd-table-custom-class thead th, .antd-table-custom-class tbody
td
{ white-space: nowrap;
word-break:break-word;
word-break: break-all
}
if antd table width 100% not working:
.ant-table-fixed {
table-layout: fixed;
}
.ant-table-tbody > tr > td {
word-wrap: break-word;
word-break: break-all;
}
Im testing using react-testing-library and jest-styled-components.
I have a wrapper component that renders the styles of its child button dependant on a selected prop passed to it.
This is the code:
const selectedStyles = css`
background-image: url(../image);
background-position: center;
background-repeat: no-repeat;
border-color: ${color.grey6};
height: 38px;
width: 58px;
& span {
display: none;
}
`;
const ButtonWrapper = styled.div`
& button {
font-size: 15px;
line-height: 20px;
padding: 8px 12px;
${props =>
props.selected
? css`
${selectedStyles}
`
: ""}
&:hover,
:focus {
${props =>
props.selected
? css`
${selectedStyles}
`
: ""}
}
}
`;
and the test
test("it renders the correct styles when selected ", () => {
const { container } = render(<CheckButton selected>Add</CheckButton>);
const button = container.querySelector("button");
expect(button).toHaveStyleRule("background-position", "center");
});
but its failing with "Property 'background-position' not found in style rules" which is true for the original button, however when its parent is passed the selected prop this style applies.
I am also doing snapshot testing with the component however not testing the props getting passed brings the test coverage down.
Can anyone help?
In general as far as nested styles testing is concerned, I would recommend testing directly the nested element.
I personally haven't figured out a way to test nested styles using the .toHaveStyle(``); (not even a simple
a {
text-decoration: none;
}
)
so I ended up querying for the exact component I wanted to test, eg:
expect(screen.getByText(/text-within-the-child-component/i)).toHaveStyle(`
text-decoration: none;
`);
In your specific case I believe the way to go is to render your component in your test directly with the props that trigger the styles you want for each case (selected in your code example).
For those who are facing the same problem toHaveStyleRule accept a third "options" parameter after property and value where you can path a modifier:
test("it renders the correct styles when selected ", () => {
render(<CheckButton selected>Add</CheckButton>);
const button = container.querySelector("button");
expect(screen.getByText("Add").parentElement).toHaveStyleRule("background-position", "center", { modifier: 'button' });
});
Here I state on the fact that "Add" is the button text and its parent is the component ButtonWrapper.
By the way, you should avoid as much as possible using querySelector (here I'm using react testing library).
https://github.com/styled-components/jest-styled-components
I have been tuning the VirtualScroll (List) component for almost whole day but no luck.
I'm building a web based chatting application in which uses the react-virtualized List to display the chatting messages. Since message may have different content and different height, I use react-measure to calculate the item height and issue the recomputeRowHeights in rowRenderer.
The result is bad, VirtuallScroll List will jump around whenever I stopped the scrolling. For example, when I scrolled to the half of browser, I should see the middle of the messages, but it always suddenly shift the offset. Please take a look at the recorded video:
https://drive.google.com/file/d/0B_W64UoqloIkcm9oQ08xS09Zc1k/view?usp=sharing
Since I only use the List and Autosizer component, I only adapt the required css file into my project which is like
```
.VirtualScroll {
width: 100%;
outline: none;
}
```
For the render method, I nested a lot of flex components inside the rowRender:
Here is the code:
```
render() {
const inChat = this.context.store.getState().inChat;
const {conversationList} = this.state;
const imgUrl = 'img/builtin-wallpaper-1.jpg';
const backgroundStyle = {
backgroundImage: 'url(' + imgUrl + ')',
backgroundRepeat: 'no-repeat',
backgroundSize: 'cover',
backgroundPosition: 'top left'
};
if (inChat.id === this.id && inChat.status === 'FETCHING'){
return (
<Box column center height="80%">
<CircularProgress />
</Box>
);
} else if (inChat.id === this.id && inChat.status === 'FETCHED'){
return (
<Box column flex="1 0 100%" style={backgroundStyle}>
<HorizontalToolBar/>
<AutoSizer disableHeight={true}>
{({ width }) => (
<List
ref={(element) => {this.VirtualScroll = element;}}
className='VirtualScroll'
height={window.innerHeight - toolbarHeight - textAreaHeight}
overscanRowCount={10}
noRowsRenderer={this._noRowsRenderer.bind(this)}
rowCount={conversationList.length}
rowHeight={i => {
return (Measured_Heights[i.index] | 20); // default Height = 58
}}
rowRenderer={this._rowRenderer}
scrollToIndex={undefined} // scroll to latest item
width={width}
/>
)}
</AutoSizer>
<InputControl chatId={this.id} sendChatText={this._sendChatText.bind(this)}/>
</Box>
);
} else {
return null;
}
}
_rowRenderer ({ index, key, style, isScrolling }) {
console.log(Measured_Heights);
const rowData = this._getDatum(index);
// let renderItem;
// console.log('index = ' + index + ' key = ' + key);
if (rowData.type == 'conversation') {
if (rowData.data.type == netModule.TYPE_SYSTEM) {
// system message
return (
<Measure key={key} onMeasure={(dims) => this._onMeasure(index, dims)}>
<SystemMessage data={rowData.data}/>
</Measure>
)
}
if (rowData.data.senderId == this.state.selfProfile.username) {
// outgoing message
return (
<Measure key={key} onMeasure={(dims) => this._onMeasure(index, dims)}>
<RightMessage
screenWidth={(window.innerWidth - leftToolBarWidth) / 2 }
screenHeight={window.innerHeight - toolbarHeight}
data={rowData.data}/>
</Measure>
);
} else {
// incoming message
// append userProfile to left messages
return (
<Measure key={key} onMeasure={(dims) => this._onMeasure(index, dims)}>
<LeftMessage
userId={rowData.data.senderId}
userProfile={this.state.groupUserProfiles[rowData.data.senderId]}
screenWidth={(window.innerWidth - leftToolBarWidth) / 2 }
screenHeight={window.innerHeight - toolbarHeight}
data={rowData.data}/>
</Measure>
);
}
}
}
```
I read a couple docs that Flexbox may be intercept the scrolling event, but even though I added overflow-y: hidden to nested component I didn't see the issue disappear. Have you ever seen this wrong scrolling behavior with List component before?
Any suggestion is welcome.
I can't see the video, but I think I had something similar recently. From what I can see, you're not making use of the style parameter passed into your _rowRenderer method. This parameter contains some CSS transforms that make the row appear at the right vertical position in the scrolling list.
I'm trying to build a div with uncertain number of child divs, I want the child div have flex="100" when there is only one of them, which takes the entire row. If there are more than one child divs (even if there are three or four child elements), they should all have exactly flex="50", which will take half of the row.
Any idea how could I do that?
Thanks in advance.
Another way is <div flex="{{::flexSize}}"></div> and in controller define and modify flexSize e.g $scope.flexSize = 50;
Thanks for the help from #William S, I shouldn't work with flex box for a static size layout.
So I work with ng-class to solve my problem.
HTML:
<div flex layout-fill layout="column" layout-wrap>
<div ng-repeat="function in functions" ng-class="test" class="card-container">
<md-card>
contents
</md-card>
</div>
</div>
My CSS is like the following:
.test1 {
width: 100%;
}
.test2 {
width: 50%;
}
The initial value of $scope.test is 'test1',by changing the value from 'test1' to 'test2', the width of children divs will be set to 50%.
Defining "flex" inside an element will always try to take up the most amount of space that the parent allows, without supplying any parameters to flex. This needs to be accompanied by layout="row/column", so flex expands in the right direction.
Is this what you're looking for?
http://codepen.io/qvazzler/pen/LVJZpR
Note that eventually, the items will start growing outside the parent size. You can solve this in several ways, but I believe this is outside the scope of the question.
HTML
<div ng-app="MyApp" ng-controller="AppCtrl as ctrl">
<h2>Static height list with Flex</h2>
<md-button class="thebutton" ng-click="addItem()">Add Item</md-button>
<div class="page" layout="row">
<md-list layout-fill layout="column">
<md-list-item flex layout="column" class="listitem" ng-repeat="item in items" ng-click="logme('Unrelated action')">
<md-item-content layout="column" md-ink-ripple flex>
<div class="inset">
{{item.title}}
</div>
</md-item-content>
</md-list-item>
</md-list>
</div>
</div>
CSS
.page {
height: 300px; /* Or whatever */
}
.thebutton {
background-color: gray;
}
.listitem {
/*height: 100px;*/
flex;
background-color: pink;
}
JS
angular.module('MyApp', ['ngMaterial'])
.controller('AppCtrl', function($scope) {
$scope.items = [{
title: 'Item One',
active: true
} ];
$scope.addItem = function() {
newitem = {
title: 'Another item',
active: false
};
$scope.items.push(newitem);
}
$scope.toggle = function(item) {
item.active = !item.active;
console.log("bool toggled");
}
$scope.logme = function(text) {
alert(text);
console.log(text);
}
});
Use below :
scope.flexSize = countryService.market === 'FR'? 40: 50;
<div flex="{{::flexSize}}">