Vuetify data table component - Truncate text in cell using CSS - css

In the following example, is there any way to use CSS to truncate the text in the cell (rather than have it wrap around or overflow)? Ideally, the CSS should look something like this:
.truncate {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
But as you can see below, this just causes the cell to consume all the space:
<!DOCTYPE html>
<html>
<head>
<link href="https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/#mdi/font#4.x/css/materialdesignicons.min.css" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/vuetify#2.x/dist/vuetify.min.css" rel="stylesheet">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no, minimal-ui">
<style>
.truncate {
display: inline-block;
/* width: 200px; */
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
</style>
</head>
<body>
<div id="app">
<v-app>
<v-content>
<v-data-table :headers="headers" :items="items">
<template v-slot:item.name="{ item }">
<span class="truncate">{{ item.name}}</span>
</template>
</v-data-table>
</v-content>
</v-app>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue#2.x/dist/vue.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vuetify#2.x/dist/vuetify.js"></script>
<script>
new Vue({
el: '#app',
vuetify: new Vuetify(),
data: {
headers: [
{ text: 'Name', value: 'name', width: "75%" },
{ text: 'Calories', value: 'calories', width: "25%" },
],
items: [
{ name: 'Frozen Yogurt', calories: 159, },
{ name: 'Ice cream sandwich with a really, really, really long name that keeps going on and on and on forever so there is no space left', calories: 237, },
{ name: 'Eclair', calories: 262, },
], }
})
</script>
</body>
</html>
It is possible to achieve the desired effect by specifying a fixed width in pixels, but I would like the table and its columns to be responsive.

If you apply the truncating to the td instead, and applying the magic hack max-width: 1px you will get your desired result.
In the example below, in order to apply the class to the td you have to use the item slot and create the row yourself.
<!DOCTYPE html>
<html>
<head>
<link href="https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/#mdi/font#4.x/css/materialdesignicons.min.css" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/vuetify#2.x/dist/vuetify.min.css" rel="stylesheet">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no, minimal-ui">
<style>
.truncate {
max-width: 1px;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
</style>
</head>
<body>
<div id="app">
<v-app>
<v-content>
<v-data-table :headers="headers" :items="items">
<template v-slot:item="{ item }">
<tr>
<td class="truncate">{{ item.name}}</td>
<td>{{ item.calories}}</td>
</tr>
</template>
</v-data-table>
</v-content>
</v-app>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue#2.x/dist/vue.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vuetify#2.x/dist/vuetify.js"></script>
<script>
new Vue({
el: '#app',
vuetify: new Vuetify(),
data: {
headers: [{
text: 'Name',
value: 'name',
width: "75%"
},
{
text: 'Calories',
value: 'calories',
width: "25%"
},
],
items: [{
name: 'Frozen Yogurt',
calories: 159,
},
{
name: 'Ice cream sandwich with a really, really, really long name that keeps going on and on and on forever so there is no space left',
calories: 237,
},
{
name: 'Eclair',
calories: 262,
},
],
}
})
</script>
</body>
</html>

It worked for me by setting the css max-with value to a responsive vw value:
.truncate {
max-width: 50vw;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}

Your code works if you just change the SPAN to a DIV and uncomment the width in the css.
<!DOCTYPE html>
<html>
<head>
<link href="https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/#mdi/font#4.x/css/materialdesignicons.min.css" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/vuetify#2.x/dist/vuetify.min.css" rel="stylesheet">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no, minimal-ui">
<style>
.truncate {
display: inline-block;
width: 200px;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
</style>
</head>
<body>
<div id="app">
<v-app>
<v-content>
<v-data-table :headers="headers" :items="items">
<template v-slot:item.name="{ item }">
<div class="truncate">{{ item.name}}</div>
</template>
</v-data-table>
</v-content>
</v-app>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue#2.x/dist/vue.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vuetify#2.x/dist/vuetify.js"></script>
<script>
new Vue({
el: '#app',
vuetify: new Vuetify(),
data: {
headers: [
{ text: 'Name', value: 'name', width: "75%" },
{ text: 'Calories', value: 'calories', width: "25%" },
],
items: [
{ name: 'Frozen Yogurt', calories: 159, },
{ name: 'Ice cream sandwich with a really, really, really long name that keeps going on and on and on forever so there is no space left', calories: 237, },
{ name: 'Eclair', calories: 262, },
], }
})
</script>
</body>
</html>

Related

Vuetify v-select component width changing

My v-select components should have a fixed width (60px), they fit in a table cell, and I want to prevent them from changing the width after value selected.
They change the width and drop-down arrow moves to the right after selection, so if there a way to decrease the size of an icon or its padding/margin it might be helpful.
Don't really know how to get props of this arrow and how this calls.
Here is the reproducible
https://codesandbox.io/s/competent-dew-eixq2?file=/src/components/Playground.vue
EDIT: Add snippet
<!DOCTYPE html>
<html>
<head>
<link href="https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/#mdi/font#4.x/css/materialdesignicons.min.css" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/vuetify#2.0.1/dist/vuetify.min.css" rel="stylesheet">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no, minimal-ui">
<style>
.select {
max-width: 60px;
max-height: 60px;
font-size: 11px;
}
.col {
max-width: 60px;
max-height: 60px;
}
</style>
</head>
<body>
<div id="app">
<v-app>
<v-row>
<div class="col" v-for="col in cols" :key="col">
<v-select class="select" :items="variants" item-value="name" item-text="name" label="" dense outlined hide-details single-line v-model="selected">
</v-select>
</div>
</v-row>
</v-app>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue#2.6.10/dist/vue.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vuetify#2.0.1/dist/vuetify.js"></script>
<script>
new Vue({
el: '#app',
vuetify: new Vuetify(),
data: {
selected: "",
cols: [1, 2, 3, 4, 5],
variants: [{
id: 0,
name: ""
},
{
id: 1,
name: "1:0"
},
{
id: 2,
name: "0:1"
},
{
id: 3,
name: "1:0 B"
},
{
id: 4,
name: "0:1 B"
},
{
id: 6,
name: "1:0 R"
},
{
id: 7,
name: "0:1 R"
},
{
id: 8,
name: "1:0 F"
},
{
id: 9,
name: "0:1 F"
},
],
},
})
</script>
</body>
</html>
The basic problem is that v-select has some styling (specifically padding and margin) that does not work very well at small widths.
This is the innerHTML of the rendered v-select, with the styles that need reducing
<div class="select...">
<div class="v-input__control">
<div role="button" class="v-input__slot"> <!-- padding-right: 12px; -->
<div class="v-select__slot">
<div class="v-select__selections">
<div class="v-select__selection--comma"> <!-- margin-right: 4px; -->
1:0 B
</div>
</div>
<div class="v-input__append-inner"> <!-- padding-left: 4px; -->
<div class="v-input__icon v-input__icon--append"> <!-- width: 24px; min-width: 24px;-->
<i aria-hidden="true" class="v-icon..."></i>
</div>
</div>
</div>
</div>
</div>
</div>
Aside from those innerHTML changes, you want a fixed width of 60px per column so change
<style>
.select {
max-width: 60px;
...
}
to
<style>
.select {
width: 60px;
...
}
Adjusting Vuetify inner styles
Looking at the Vuetify issues around styling, there's suggestions of using un-scoped style blocks, or deep-scoped style blocks, but neither worked for me. Vuetify have said they are working on a revamp of the way styles are applied to overcome the issues.
Fortunately Vue itself has tools to do it in javascript.
These are the key steps
add a reference to the v-select so that it's accessible in javascript
add a change handler to the v-select so that elements can be re-styled when the user selects something
define the style adjustments in an object so you can easily tweak them
add a method to apply the styles
call the method in mounted() and the v-select #change handler
use Vue.nextTick() to allow Vuetify to style first, then our custom styles are applied
Here's the adjusted code snippet. I put in some severely minimal padding and margins, and maximized the space for the selected value (to avoid text wrapping). You may want to play with the styles as I'm not sure I understood all of the requirements.
<!DOCTYPE html>
<html>
<head>
<link href="https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/#mdi/font#4.x/css/materialdesignicons.min.css" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/vuetify#2.0.1/dist/vuetify.min.css" rel="stylesheet">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no, minimal-ui">
<style>
.select {
width: 60px;
max-height: 60px;
font-size: 11px;
}
.col {
max-width: 60px;
max-height: 60px;
}
</style>
</head>
<body>
<div id="app">
<v-app>
<v-row>
<div class="col" v-for="col in cols" :key="col">
<v-select ref="select" #change="applyCustomStyles"
class="select" :items="variants" item-value="name" item-text="name" label="" dense outlined hide-details single-line v-model="selected">
</v-select>
</div>
</v-row>
</v-app>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue#2.6.10/dist/vue.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vuetify#2.0.1/dist/vuetify.js"></script>
<script>
const customStyles = {
".v-input__slot": {
padding: "0 0 0 4px",
},
".v-select__selections": {
width: "27px",
},
".v-select__selection--comma": {
margin: "7px 0 7px 0",
},
".v-input__append-inner": {
"padding-left": "0",
},
".v-input__icon": {
width: "14px",
"min-width": "14px",
},
};
new Vue({
el: '#app',
vuetify: new Vuetify(),
mounted() {
this.applyCustomStyles();
},
methods: {
applyCustomStyles() {
Vue.nextTick(() => {
this.$refs.select.forEach((vSelect) => {
Object.entries(customStyles).forEach(([selector, styles]) => {
Object.entries(styles).forEach(([style, value]) => {
vSelect.$el.querySelector(selector).style[style] = value;
});
});
});
});
},
},
data: {
selected: "",
cols: [1, 2, 3, 4, 5],
variants: [{
id: 0,
name: ""
},
{
id: 1,
name: "1:0"
},
{
id: 2,
name: "0:1"
},
{
id: 3,
name: "1:0 B"
},
{
id: 4,
name: "0:1 B"
},
{
id: 6,
name: "1:0 R"
},
{
id: 7,
name: "0:1 R"
},
{
id: 8,
name: "1:0 F"
},
{
id: 9,
name: "0:1 F"
},
],
},
})
</script>
</body>
</html>
Why not a <style> block?
There are suggestions of using an un-scoped style block to override the Vuetify styles.
For example,
<style>
.select .v-input__slot {
padding-right: 4px
}
...
</style>
The problem is the Vuetify styles are getting applied after those declared on the component.
You can do it by applying greater specificity than Vuetify uses, e.g.
<style>
.select.v-text-field.v-text-field--enclosed:not(.v-text-field--rounded)>.v-input__control>.v-input__slot {
padding-right: 4px
}
</style>
gives you this
so you can hunt out all the existing places where a change is necessary and copy the Vuetify selector.
The problems might occur when a new version of Vuetify is used, or the shape of the component is changed. To me, the javascript solution looks more manageable.
1. If you don't care about the appended icon, you can remove it with the use of append-icon prop (pass empty value):
<v-select
class="select"
...
append-icon=""
></v-select>
2. You can override the slot for the icon with your own content:
<v-select
class="select"
...
>
<template #append>
<div class="my-custom-icon">...</div>
</template>
</v-select>
Then add style to your my-custom-icon class to make it appear in one place:
.my-custom-icon {
position: absolute;
left: ...;
right: ...;
}
3. Make use of overflow: hidden property:
<style> // don't add "scoped" attribute, otherwise the style won't be applied
.select .v-input__control {
overflow: hidden;
}
</style>
Hello I have facing same problem but as I am using custom made select from vuetify v-select i can not overwrite CSS because it will change drop-down in whole project and this will be the case for all devloper working on projects
So simple solution will be make container div and give it min-width max width and width as you see fit it will solve your size change issue with table cell
It worked for me as i set my drop-down min width to max-width of container so it will be same same width
Ex
<div :class='container'>
<v-select />
</div>
<style>
. container {
max-width: 9rem // in my case it's the min width for my default selected option
}
</style>

Change color of v-select selected element using CSS

I have the following v-select
Vue.config.productionTip = false;
Vue.config.devtools = false;
new Vue({
el: '#app',
vuetify: new Vuetify(),
data(){
return{
company_roles:[{
value: 1,
text: 'CEO'
},
{
value: 2,
text: 'Project Manager'
},
]
}
}
})
.v-list-item__title:hover{
color: #ffd54f !important;
}
<link href="https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/#mdi/font#4.x/css/materialdesignicons.min.css" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/vuetify#2.x/dist/vuetify.min.css" rel="stylesheet">
<script src="https://cdn.jsdelivr.net/npm/vue#2.x/dist/vue.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vuetify#2.x/dist/vuetify.js"></script>
<div id="app">
<v-app>
<v-row>
<v-col cols="12" sm="12" md="6">
<v-select :items="company_roles" label="Role in Company" solo color="yellow"></v-select>
</v-col>
</v-row>
</v-app>
</div>
I could change the hover color before select, but after it's selected, if you open the dropdown again the background and the color are blue, I don't know how to change those. I would like a solution using CSS, not SCSS, thanks.
You can modify css like:
.v-list .v-list-item--active {
background-color: green!important;
}
.v-list .v-list-item--active .v-list-item__title {
color: #ffd54f !important;
}
you can update the colors as per your requirement here. For demo, I have added background green and text color #ffd54f
Working Demo:
Vue.config.productionTip = false;
Vue.config.devtools = false;
new Vue({
el: '#app',
vuetify: new Vuetify(),
data(){
return{
company_roles:[{
value: 1,
text: 'CEO'
},
{
value: 2,
text: 'Project Manager'
},
]
}
}
})
.v-list-item__title:hover{
color: #ffd54f !important;
}
.v-list .v-list-item--active {
background-color: green!important;
}
.v-list .v-list-item--active .v-list-item__title {
color: #ffd54f !important;
}
<link href="https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/#mdi/font#4.x/css/materialdesignicons.min.css" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/vuetify#2.x/dist/vuetify.min.css" rel="stylesheet">
<script src="https://cdn.jsdelivr.net/npm/vue#2.x/dist/vue.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vuetify#2.x/dist/vuetify.js"></script>
<div id="app">
<v-app>
<v-row>
<v-col cols="12" sm="12" md="6">
<v-select :items="company_roles" label="Role in Company" solo color="yellow"></v-select>
</v-col>
</v-row>
</v-app>
</div>

How to remove hover effect on selected row?

I changed the .k-state-selected to a different color, works fine. However when I hover over the selected row the hover color is blue.
I have tried
.k-grid tr:hover{
background:transparent;
}
and that works fine for rows that are not selected, but not for the selected row.
Essentially I need to remove the hover effect on a selected row and can't figure it out
$("#grid").kendoGrid({
columns: [{
field: "name"
},
{
field: "age"
}
],
dataSource: [{
name: "Jane Doe",
age: 30
},
{
name: "John Doe",
age: 33
}
],
selectable: "row"
});
.k-grid .k-state-selected {
background: #ec971f;
}
<link rel="stylesheet" href="https://kendo.cdn.telerik.com/2019.3.1023/styles/kendo.common.min.css" />
<link rel="stylesheet" href="https://kendo.cdn.telerik.com/2019.3.1023/styles/kendo.rtl.min.css" />
<link rel="stylesheet" href="https://kendo.cdn.telerik.com/2019.3.1023/styles/kendo.silver.min.css" />
<link rel="stylesheet" href="https://kendo.cdn.telerik.com/2019.3.1023/styles/kendo.mobile.all.min.css" />
<script src="https://code.jquery.com/jquery-1.12.4.min.js"></script>
<script src="https://kendo.cdn.telerik.com/2019.3.1023/js/kendo.all.min.js"></script>
<div id="grid"></div>
Try it:
$("#grid").kendoGrid({
columns: [{
field: "name"
},
{
field: "age"
}
],
dataSource: [{
name: "Jane Doe",
age: 30
},
{
name: "John Doe",
age: 33
}
],
selectable: "row"
});
.k-grid .k-state-selected {
background: #ec971f;
}
.k-grid .k-state-selected:hover {
background: #ec971f!important;
color:#000;
}
<link rel="stylesheet" href="https://kendo.cdn.telerik.com/2019.3.1023/styles/kendo.common.min.css" />
<link rel="stylesheet" href="https://kendo.cdn.telerik.com/2019.3.1023/styles/kendo.rtl.min.css" />
<link rel="stylesheet" href="https://kendo.cdn.telerik.com/2019.3.1023/styles/kendo.silver.min.css" />
<link rel="stylesheet" href="https://kendo.cdn.telerik.com/2019.3.1023/styles/kendo.mobile.all.min.css" />
<script src="https://code.jquery.com/jquery-1.12.4.min.js"></script>
<script src="https://kendo.cdn.telerik.com/2019.3.1023/js/kendo.all.min.js"></script>
<div id="grid"></div>
.k-grid tr:hover doesn't work because of the rules of CSS specificity. In other words, .k-grid .k-state-selected is more specific than .k-grid tr:hover.
.k-grid .k-state-selected:hover should work for you.
Example

fullcalendar, can i add location from gcal and can i give different colors based on different location events (from the same calendar)

this is my code, the calendar and events display correctly but i want to give them more color and a location, can somebody please help?
<!DOCTYPE html> <html> <head> <meta charset='utf-8' />
<link href='fullcalendar-3.8.0/fullcalendar.min.css' rel='stylesheet' />
<link href='fullcalendar-3.8.0/fullcalendar.print.min.css' rel='stylesheet' media='print' />
<script src='fullcalendar-3.8.0/lib/moment.min.js'></script>
<script src='fullcalendar-3.8.0/lib/jquery.min.js'></script>
<script src='fullcalendar-3.8.0/fullcalendar.min.js'></script>
<script src='fullcalendar-3.8.0/gcal.min.js'></script>
<script>
$(document).ready(function() {
$('#calendar').fullCalendar({
header: {
left: 'prev,next today',
center: 'title',
right: 'month,agendaWeek,agendaDay'
},
displayEventTime: true, // don't show the time column in list view
editable: true, defaultView: 'agendaWeek',
googleCalendarApiKey: 'private',
// Key van de google calender
events: { url:'private' },
eventClick: function(event) {
// opens events in a popup window
window.open(event.url, 'gcalevent', 'width=700,height=600');
return false;
},
loading: function(bool) {
$('#loading').toggle(bool);
}
});
});
</script>
<style>
body {
margin: 40px 10px;
padding: 0;
font-family: "Lucida Grande",Helvetica,Arial,Verdana,sans-serif;
font-size: 14px;
}
#loading {
display: none;
position: absolute;
top: 10px;
right: 10px;
}
#calendar {
max-width: 900px;
margin: 0 auto; }
</style>
</head>
<body>
<div id='loading'>loading...</div>
<div id='calendar'></div>
</body>
</html>

Angular 2: No spacing between bootstrap buttons

On the following site: http://getbootstrap.com/css/#buttons
There is a space between the demo buttons on the boostrap site, but when I used them on my site, there's no space between. I've used developer tools to examine the styles but can't figure out what's causing that space.
Here's the code:
app.ts
//our root app component
import {Component, NgModule} from '#angular/core'
import {BrowserModule} from '#angular/platform-browser'
#Component({
selector: 'my-app',
template: `
<div>
<h2>Hello {{name}}</h2>
<button type="button" class="btn btn-primary" *ngFor="let room of rooms">{{room.Name}}</button>
</div>
`,
})
export class App {
name:string;
rooms:Array<any> = [
{Name: 'Room 1'},
{Name: 'Room 2'},
{Name: 'Room 3'},
{Name: 'Room 4'},
]
constructor() {
this.name = 'Angular2'
}
}
#NgModule({
imports: [ BrowserModule ],
declarations: [ App ],
bootstrap: [ App ]
})
export class AppModule {}
index.html
<!DOCTYPE html>
<html>
<head>
<base href="." />
<title>angular2 playground</title>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
<link rel="stylesheet" href="style.css" />
<script src="https://unpkg.com/core-js#2.4.1/client/shim.min.js"></script>
<script src="https://unpkg.com/zone.js/dist/zone.js"></script>
<script src="https://unpkg.com/zone.js/dist/long-stack-trace-zone.js"></script>
<script src="https://unpkg.com/reflect-metadata#0.1.3/Reflect.js"></script>
<script src="https://unpkg.com/systemjs#0.19.31/dist/system.js"></script>
<script src="config.js"></script>
<script>
System.import('app')
.catch(console.error.bind(console));
</script>
</head>
<body>
<my-app>
loading...
</my-app>
</body>
</html>
Here is a plunker showing my code: https://plnkr.co/edit/68Au4swU0Oi63PQFOn5L?p=preview
Can anyone help?
The reason for this behavior in contrary of the demo you provided, is that you are iterating the buttons. If you add them without the loop, they render just like as you would wish. I would suggest you actually use CSS for this purpose. Just add a margin between the buttons in CSS:
.btn{
margin: 5px;
}
Your updated Plunker
in angular to fix that issue you need to add preserveWhitespaces: true the tsConfig :
"angularCompilerOptions": {
"enableI18nLegacyMessageIdFormat": false,
"strictInjectionParameters": true,
"strictInputAccessModifiers": true,
"strictTemplates": true,
"preserveWhitespaces": true // add this line in tsconfig.json
}
Their display property set to inline-block which add 4px space by default.....that's why people don't use display: inline-block to create flexible grid

Resources