I'm trying to hide a column in ag-grid on mobile.
I'm using ag-grid for a vue.js app. I have tired the below code, but it's not working properly.
{
headerName: "Action",
field: "action",
minWidth: 54,
suppressMovable: true,
editable: true,
hide : ( window.innerWidth < 786 ? true : false )
}
I expect the output to be hide this column on mobile and show on desktop, but the output is bit strange to me. Initially when I load the page on mobile and desktop the column hide/show accordingly, but on mobile it's also hide some of other column's header titles(only header titles). Also when I resize the window from mobile to desktop the require column won't show and also resizing from desktop to mobile won't hide the required column.
You should use columnApi.setColumnVisible("your_column", false).
To be able to do so, first save the columnApi on #grid-ready
<template>
<ag-grid-vue style="width: 500px; height: 500px;"
class="ag-theme-balham"
:columnDefs="columnDefs"
:rowData="rowData"
rowSelection="multiple"
#grid-ready="onGridReady">
</template>
...
import {AgGridVue} from "ag-grid-vue";
const hideActionColumn = () => {
if(this.columnApi) {
this.columnApi.setColumnVisible("action", true);
if(window.innerWidth < 786) {
this.columnApi.setColumnVisible("action", false);
}
}
}
export default {
name: 'App',
data() {
return {
columnDefs: null,
rowData: null
}
},
components: {
AgGridVue
},
methods: {
onGridReady(params) {
this.columnApi = params.columnApi;
}
},
mounted() {
// hide the column, if the initial load is in mobile view
hideActionColumn();
window.addEventListener('resize', hideActionColumn);
},
beforeDestroy() {
window.removeEventListener('resize', hideActionColumn);
}
}
Then you need to appends an event listener, so you can call hideActionColumn() on window.resize
window.addEventListener('resize', hideActionColumn);
Also you need to remove the event listener, before your component is destroyed.
I hope this will help you.
Regards
Related
I have a datagrid using MUI and I have came across a use case where I need to hide one of the columns if I do not have a certain role. Here is the code.
const hideColumn = () => {
const globalAdmin = auth.verifyRole(Roles.Admin);
if(!globalAdmin){
return true;
}
return false;
};
const columns = [
{ field: 'id', headerName: 'ID', width: 100 },
{ field: 'name',
headerName: 'Client code',
flex: 1,
hide: hideColumn,
renderCell: (params) => {
return params.getValue("name");
},
},
];
I'm confused on why this is not working. If I just use hide:true or hide:false it works but I need have an if statement to check the credentials first and this can't be done in the renderCell (or at least I can't get it to work). Does anyone know how to do this correctly?
You should call it as function hide: hideColumn()
Or you can create a function to retrieve your columns and pass props to this function. Then you just have to push your columns according to criteria:
export default function getColumns (product, isHide, t) {
let columns = [
{
field: 'organizationName',
headerName: headerNameOrganization,
flex: 0.3,
},
]
if (!product) {
columns.push(
{
field: 'status',
headerName: headerNameStatus,
flex: 0.2,
filterable: false,
})
}
return columns
}
Use the prop columnVisibilityModel of <DataGrid /> to control the column visibility dynamically.
The prop can also have a listener.
You can use the onColumnVisibilityModelChange prop to listen to the changes to the visible columns and update the prop accordingly.
(MUI doc)
At first, I was using the initialState (as the ff), but MUI said in their documentation:
The initialState can only be used to set the initial value of the state, the grid will not react if you change the initialState value later on.
If you need to fully control specific models, use the control props instead...
<DataGrid
columns={columns}
rows={rows}
loading={!users.length}
initialState={{
columns: {
columnVisibilityModel: {
myColumn1: isAdmin(user),
myColumn2: isAdmin(user),
},
},
}}
/>
Im under the assumption that v-show will show/hide elements based on its passed data.
For some reason, my element will not hide dynamically when v-show is false. When I manually change the variable (showNav) to false, it will be hidden on page load so it seems to functioning properly.
My variable (showNav) depends on scroll. When scroll up, it is set to true, when scroll down it is set to false. I'd like my nav bar to hide on scroll down but that is not happening.
The scroll behavior is behaving properly. Both are properly changing my v-show variable (showNav) to either true or false but the element remains visible at all times.
HTML template
<template>
<div id="home-page">
<Navbar id="navbar" v-show="showNav" :class="{change_background: scrollPosition > 50}" />
</div>
</template>
JS
mounted() {
window.addEventListener('scroll', function(){
// detects new state and compares it with the old one
if ((document.body.getBoundingClientRect()).top > this.scrollPos) {
this.showNav = true;
console.log(this.showNav);
}
else
{
this.showNav = false;
console.log(this.showNav);
}
// saves the new position for iteration.
this.scrollPos = (document.body.getBoundingClientRect()).top;
})
},
data() {
return {
scrollPosition: null,
scrollPos: 0,
showNav: true,
}
},
You need to handle the scroll events by binding one of the methods defined within the methods block to the scroll event of the window. In your case the callback function passed to the scroll event listen will not have access to the vue instance and hence it will not update the reactive properties of vuejs. See the working sample below.
new Vue({
el: "#app",
data() {
return {
scrollPosition: null,
scrollPos: 0,
showNav: true,
}
},
mounted() {
window.addEventListener('scroll', this.handleScroll);
},
beforeDestroy() {
window.removeEventListener('scroll', this.handleScroll); // To avoid memory leakage
},
methods: {
handleScroll(event) {
// detects new state and compares it with the old one
if ((document.body.getBoundingClientRect()).top > this.scrollPos) {
this.showNav = true;
console.log(this.showNav);
} else {
this.showNav = false;
console.log(this.showNav);
}
// saves the new position for iteration.
this.scrollPos = (document.body.getBoundingClientRect()).top;
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app" style="min-height: 1000px;">
<span v-show="showNav">You are trying to hide me</span>
</div>
I am using the Angular Material Tab component along with AG Grid like below
<mat-tab-group>
<mat-tab label="First Tab">
<app-grid-component1></app-grid-component1> //First Component
</mat-tab>
<mat-tab label="Second Tab">
<app-grid-component2></app-grid-component2>
</mat-tab>
</mat-tab-group>
I have created Tool tip component
agInit(params: ToolTipParams): void {
this.params = params;
if (params.lineBreak === true) {
this.toolTip = params.toolTipArray.join('\n');
} else if (params.lineBreak === false) {
this.toolTip = params.toolTip;
} else {
this.toolTip = params.value;
}
}
refresh(params: ToolTipParams): boolean {
this.params = params;
return true;
}
And my first component works fine and show the tooltip on every cell
this.gridOptions = {
deltaRowDataMode: true,
rowSelection: 'single',
defaultColDef: {
sortable: true,
resizable: true,
// PLACE HERE TO EFFECT ALL COLUMNS
cellRendererFramework: ToolTipComponent,
cellRendererParams: (params: ICellRendererParams) => this.formatToolTip(params.data)
}
};
But if I click and go to the Second tab with the same configuration as the first tab, the tooltip shows for the first two columns perfectly but does not show from 3rd column on hover...I can only see a little black box without the content but if I click the cells I can see the tooltip content. I did put the log and checked aginit function in tooltip component loads with data but the tooltip does not show any data on hover.
First, the terms, "link" is the area where the mouse enters. The "tooltip" is the thing that pops up and shows extra information.
--- above added 2020-04-29
I'm using Vuetify and trying to keep the v-tooltip open when mouse is hovering over the "tooltip".
The content inside the tooltip is going to be rich and don't want that to automatically hide when visitor is looking into it.
<template>
<v-tooltip
v-model="show"
max-width="600px"
content-class="link-tooltip-content"
bottom>
<template v-slot:activator="{ on }">
<div
:style="boxStyle"
#mouseover="mouseover"
#mouseleave="mouseleave"
></div>
</template>
<template v-slot:default>
<v-card
#mouseover="mouseover"
#mouseleave="mouseleave"
>
<v-row dense>
<v-col>
<v-card-title class="headline">
rich tooltip
</v-card-title>
</v-col>
</v-row>
</v-card>
</template>
</v-tooltip>
</template>
<script>
export default {
data: () => ({
show: false,
hoverTimer: null
}),
methods: {
boxStyle: function() {
return {
left: "100px",
top: "100px",
width: "100px",
height: "100px",
position: "absolute"
};
},
mouseover: function() {
console.log(`mouseover`);
this.show = true;
clearTimeout(this.hoverTimer);
},
mouseleave: function() {
console.log(`mouseleave`);
this.hoverTimer = setTimeout(() => {
this.show = false;
}, 3000);
}
}
};
</script>
But this doesn't work. The mouseover and mouseleave event handlers on the activator slot (the "link") element does fire, but the event handlers on the default slot (the "tooltip") don't fire.
I think the reason is, because the content inside the "tooltip" is moved to somewhere else under the body tag.
The questions is, how can I keep the "tooltip" open when hovering over it.
I'm moving the mouse like this:
Hover over the link (the tooltip shows up).
Move the mouse out of the link and into the tooltip. (The link and tooltip is a few pixels apart)
Now the mouseleave event for the link fires, and I want to add a mouseenter event handler on the tooltip. How do I do that ?
I'm thinking to add an mouseenter event on the tooltip, so that I can clearTimeout(hoverTimer) and keep the tooltip open.
I know there's a similar question from 9 years ago, using jQuery Keep tooltip opened when the mouse is over it , but I don't want to use jQuery if possible. I prefer a Vue way.
Here's a little reproducible example:
https://www.codeply.com/p/GuFXqAAU8Y
Instead of using v-tooltip, I suggest you use v-menu with the open-on-hover props set to true.
If you have to nudge whatever you put in the menu, make sure to set an appropriate close-delay value, so the menu doesn't close before the user reaches it.
Example:
https://codepen.io/stephane303/pen/WNwdNxY
<v-menu open-on-hover right offset-x nudge-right="20" close-delay="100">
.v-tooltip__content has pointer-events:none set in vuetify.min.css. If you set it back to auto you allow it to be hovered.
When its hovered, its parent is hovered. And when its parent is hovered, it has a tooltip. So all you need is:
.v-tooltip__content {
pointer-events: auto;
}
I made extended version of VTooltip for this purpose. Just pass interactive prop. See working example here by hovering Governance stepper: https://tzkt.io
<script>
/**
* Extends VTooltip with interactivity
* #see https://material-ui.com/components/tooltips/#interactive
*/
import { VTooltip } from 'vuetify/lib';
export default {
extends: VTooltip,
props: {
interactive: {
type: Boolean,
default: false,
},
closeDelay: {
type: [Number, String],
default: 50,
},
},
computed: {
// I'm not 100% sure in this, but it works
calculatedLeft() {
const originalValue = VTooltip.options.computed.calculatedLeft.call(this);
if (!this.interactive) return originalValue;
const { left, right } = this;
let value = parseInt(originalValue);
if (left || right) {
value += right ? -10 : 10;
}
return `${value}px`;
},
calculatedTop() {
const originalValue = VTooltip.options.computed.calculatedTop.call(this);
if (!this.interactive) return originalValue;
const { top, bottom } = this;
let value = parseInt(originalValue);
if (top || bottom) {
value += bottom ? -10 : 10;
}
return `${value}px`;
},
styles() {
const originalValue = VTooltip.options.computed.styles.call(this);
if (!this.interactive) return originalValue;
const {
top, bottom, left, right,
} = this;
let paddingDirection;
if (bottom) paddingDirection = 'top';
else if (top) paddingDirection = 'bottom';
else if (right) paddingDirection = 'left';
else if (left) paddingDirection = 'right';
return {
...originalValue,
[`padding-${paddingDirection}`]: `${10}px`,
};
},
},
methods: {
onTooltipMouseenter(e) {
if (this.interactive) {
this.clearDelay();
this.isActive = true;
}
this.$emit('tooltip:mouseenter', e);
},
onTooltipMouseleave(e) {
if (this.interactive) {
this.clearDelay();
this.runDelay('close');
}
this.$emit('tooltip:mouseleave', e);
},
genContent() {
const content = this.$createElement('div', this.setBackgroundColor(this.color, {
style: this.contentStyles,
staticClass: 'v-tooltip__content',
class: {
[this.contentClass]: true,
menuable__content__active: this.isActive,
},
}), this.getContentSlot());
return this.$createElement('div', {
style: this.styles,
attrs: this.getScopeIdAttrs(),
class: {
'v-tooltip__wrapper': true,
'v-tooltip__wrapper--fixed': this.activatorFixed,
},
directives: [{
name: 'show',
value: this.isContentActive,
}],
on: {
mouseenter: this.onTooltipMouseenter,
mouseleave: this.onTooltipMouseleave,
},
ref: 'content',
}, [content]);
},
genActivatorListeners() {
const listeners = VTooltip.options.methods.genActivatorListeners.call(this);
if (this.interactive) {
if (listeners.mouseenter) {
listeners.mouseenter = (e) => {
this.getActivator(e);
this.clearDelay();
if (!this.isActive) {
this.runDelay('open');
}
};
}
}
return listeners;
},
},
};
</script>
<style lang="scss">
.v-tooltip__wrapper {
position: absolute;
&--fixed {
position: fixed;
}
.v-tooltip__content {
position: static;
}
}
</style>
Code is in: VueJS
Hi,
I'm curious how to show a component once and then never again. I've tried v-if and v-model but none of them seem to work.
This is my code:
<template >
<div id="fakeLoader" v-if="show"></div>
</template>
<script>
import $ from 'jquery'
import '../../bower_components/fakeLoader/fakeLoader.min'
export default {
name: 'Fakeloader',
data() {
return {
show: true
};
},
methods: {
showLoader() {
this.show = false;
}
},
mounted () {
$(document).ready(function () {
// Init Fakeloader
$('#fakeLoader').fakeLoader({
timeToHide: 800,
spinner: 'spinner5',
bgColor: '#274156'
}
);
});
this.showLoader();
}
}
</script>
<style>
#import '../../bower_components/fakeLoader/fakeLoader.css';
#fakeLoader {
z-index: 999999 !important;
}
</style>
I'm setting a boolean called show and make it false whenever the jQuery function is called and make it permanently false so this component will not show again FOR THE CURRENT SESSION. So if the user opens another tab, the fakeloader should appear again at the beginning.
You might want to look into v-cloak. It allows you to segment areas of your site based on whether vue is loaded or not.
For your example, I'd have a CSS sheet comprised of
#app[v-cloak] {
display: none
}
#fakeloader {
display: none
}
#fakeloader[v-cloak] {
display: block
}
Then
<div id="app">
<div id="fakeloader" v-cloak>
This is my loader
</div>
<div id="content" v-cloak>
This is my page
</div>
</div>
This will let your app have preference when vue is loaded and the loader having preference when vue is loading.
EDIT: Just to show why a fiddle is a good thing to have before you answer. I have a fiddle up here which should demonstrate and I fixed the code.