Ag Grid, prevent column hide/show using the column menu - vue.js

How could I prevent column hide/show using the column menu in Ag Grid?
E.g. let us take the example from over here.
index.html:
<!DOCTYPE html>
<html lang="en">
<head>
<title>Vue example</title>
<meta charSet="UTF-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1"/>
<style media="only screen">
html, body, #app {
height: 100%;
width: 100%;
margin: 0;
box-sizing: border-box;
-webkit-overflow-scrolling: touch;
}
html {
position: absolute;
top: 0;
left: 0;
padding: 0;
overflow: auto;
}
body {
padding: 1rem;
overflow: auto;
}
</style>
<link rel="stylesheet" href="styles.css"/>
</head>
<body>
<div id="app">
<my-component>Loading Vue example…</my-component>
</div>
<script>
var appLocation = './';
var boilerplatePath = '';
var systemJsMap = {
"#ag-grid-community/core/dist/styles": "https://unpkg.com/#ag-grid-community/core#27.3.0/dist/styles",
"#ag-grid-community/vue": "https://unpkg.com/#ag-grid-community/vue#27.3.0/",
"ag-grid-community": "https://unpkg.com/ag-grid-community#27.3.0/",
"ag-grid-enterprise": "https://unpkg.com/ag-grid-enterprise#27.3.0/",
"ag-grid-vue": "https://unpkg.com/ag-grid-vue#27.3.0/"
};
var systemJsPaths = {
"#ag-grid-community/client-side-row-model": "https://unpkg.com/#ag-grid-community/client-side-row-model#27.3.0/dist/client-side-row-model.cjs.min.js",
"#ag-grid-community/core": "https://unpkg.com/#ag-grid-community/core#27.3.0/dist/core.cjs.min.js",
"#ag-grid-community/csv-export": "https://unpkg.com/#ag-grid-community/csv-export#27.3.0/dist/csv-export.cjs.min.js",
"#ag-grid-community/infinite-row-model": "https://unpkg.com/#ag-grid-community/infinite-row-model#27.3.0/dist/infinite-row-model.cjs.min.js",
"#ag-grid-enterprise/charts": "https://unpkg.com/#ag-grid-enterprise/charts#27.3.0/dist/charts.cjs.min.js",
"#ag-grid-enterprise/clipboard": "https://unpkg.com/#ag-grid-enterprise/clipboard#27.3.0/dist/clipboard.cjs.min.js",
"#ag-grid-enterprise/column-tool-panel": "https://unpkg.com/#ag-grid-enterprise/column-tool-panel#27.3.0/dist/column-tool-panel.cjs.min.js",
"#ag-grid-enterprise/core": "https://unpkg.com/#ag-grid-enterprise/core#27.3.0/dist/core.cjs.min.js",
"#ag-grid-enterprise/excel-export": "https://unpkg.com/#ag-grid-enterprise/excel-export#27.3.0/dist/excel-export.cjs.min.js",
"#ag-grid-enterprise/filter-tool-panel": "https://unpkg.com/#ag-grid-enterprise/filter-tool-panel#27.3.0/dist/filter-tool-panel.cjs.min.js",
"#ag-grid-enterprise/master-detail": "https://unpkg.com/#ag-grid-enterprise/master-detail#27.3.0/dist/master-detail.cjs.min.js",
"#ag-grid-enterprise/menu": "https://unpkg.com/#ag-grid-enterprise/menu#27.3.0/dist/menu.cjs.min.js",
"#ag-grid-enterprise/multi-filter": "https://unpkg.com/#ag-grid-enterprise/multi-filter#27.3.0/dist/multi-filter.cjs.min.js",
"#ag-grid-enterprise/range-selection": "https://unpkg.com/#ag-grid-enterprise/range-selection#27.3.0/dist/range-selection.cjs.min.js",
"#ag-grid-enterprise/rich-select": "https://unpkg.com/#ag-grid-enterprise/rich-select#27.3.0/dist/rich-select.cjs.min.js",
"#ag-grid-enterprise/row-grouping": "https://unpkg.com/#ag-grid-enterprise/row-grouping#27.3.0/dist/row-grouping.cjs.min.js",
"#ag-grid-enterprise/server-side-row-model": "https://unpkg.com/#ag-grid-enterprise/server-side-row-model#27.3.0/dist/server-side-row-model.cjs.min.js",
"#ag-grid-enterprise/set-filter": "https://unpkg.com/#ag-grid-enterprise/set-filter#27.3.0/dist/set-filter.cjs.min.js",
"#ag-grid-enterprise/side-bar": "https://unpkg.com/#ag-grid-enterprise/side-bar#27.3.0/dist/side-bar.cjs.min.js",
"#ag-grid-enterprise/sparklines": "https://unpkg.com/#ag-grid-enterprise/sparklines#27.3.0/dist/sparklines.cjs.min.js",
"#ag-grid-enterprise/status-bar": "https://unpkg.com/#ag-grid-enterprise/status-bar#27.3.0/dist/status-bar.cjs.min.js",
"#ag-grid-enterprise/viewport-row-model": "https://unpkg.com/#ag-grid-enterprise/viewport-row-model#27.3.0/dist/viewport-row-model.cjs.min.js"
};
</script>
<script src="https://unpkg.com/systemjs#0.19.47/dist/system.js">
</script>
<script src="systemjs.config.js">
</script>
<script>System.import('./main.js').catch(function(err) { console.error(err); });</script>
</body>
</html>
main.js:
import 'ag-grid-community/dist/styles/ag-grid.css';
import 'ag-grid-community/dist/styles/ag-theme-alpine.css';
import 'ag-grid-enterprise';
import { AgGridVue } from 'ag-grid-vue';
import Vue from 'vue';
const VueExample = {
template: `
<div style="height: 100%">
<div class="example-wrapper">
<div>
<span class="button-group">
<button v-on:click="showPivotModeSection()">Show Pivot Mode Section</button>
<button v-on:click="showRowGroupsSection()">Show Row Groups Section</button>
<button v-on:click="showValuesSection()">Show Values Section</button>
<button v-on:click="showPivotSection()">Show Pivot Section</button>
</span>
</div>
<ag-grid-vue
style="width: 100%; height: 100%;"
class="ag-theme-alpine"
:columnDefs="columnDefs"
#grid-ready="onGridReady"
:defaultColDef="defaultColDef"
:sideBar="sideBar"
:rowData="rowData"></ag-grid-vue>
</div>
</div>
`,
components: {
'ag-grid-vue': AgGridVue,
},
data: function () {
return {
columnDefs: [
{ headerName: 'Name', field: 'athlete', minWidth: 200 },
{ field: 'age', enableRowGroup: true },
{ field: 'country', minWidth: 200 },
{ field: 'year' },
{ field: 'date', suppressColumnsToolPanel: true, minWidth: 180 },
{ field: 'sport', minWidth: 200 },
{ field: 'gold', aggFunc: 'sum' },
{ field: 'silver', aggFunc: 'sum' },
{ field: 'bronze', aggFunc: 'sum' },
{ field: 'total', aggFunc: 'sum' },
],
gridApi: null,
columnApi: null,
defaultColDef: {
flex: 1,
minWidth: 100,
sortable: true,
enablePivot: true,
},
sideBar: null,
rowData: null,
};
},
created() {
this.sideBar = {
toolPanels: [
{
id: 'columns',
labelDefault: 'Columns',
labelKey: 'columns',
iconKey: 'columns',
toolPanel: 'agColumnsToolPanel',
toolPanelParams: {
suppressRowGroups: true,
suppressValues: true,
suppressPivots: true,
suppressPivotMode: true,
suppressColumnFilter: true,
suppressColumnSelectAll: true,
suppressColumnExpandAll: true,
},
},
],
defaultToolPanel: 'columns',
};
},
methods: {
showPivotModeSection() {
var columnToolPanel = this.gridApi.getToolPanelInstance('columns');
columnToolPanel.setPivotModeSectionVisible(true);
},
showRowGroupsSection() {
var columnToolPanel = this.gridApi.getToolPanelInstance('columns');
columnToolPanel.setRowGroupsSectionVisible(true);
},
showValuesSection() {
var columnToolPanel = this.gridApi.getToolPanelInstance('columns');
columnToolPanel.setValuesSectionVisible(true);
},
showPivotSection() {
var columnToolPanel = this.gridApi.getToolPanelInstance('columns');
columnToolPanel.setPivotSectionVisible(true);
},
onGridReady(params) {
this.gridApi = params.api;
this.gridColumnApi = params.columnApi;
const updateData = (data) => params.api.setRowData(data);
fetch('https://www.ag-grid.com/example-assets/olympic-winners.json')
.then((resp) => resp.json())
.then((data) => updateData(data));
},
},
};
new Vue({
el: '#app',
components: {
'my-component': VueExample,
},
});
style.css:
.example-wrapper {
display: flex;
flex-direction: column;
height: 100%;
}
#myGrid {
flex: 1 1 0px;
width: 100%;
}
.button-group {
padding-bottom: 4px;
display: inline-block;
font-family: Verdana, Geneva, Tahoma, sans-serif;
font-size: 13px;
}
When I go to the Name's column menu I can hide/show the Age column. I do not want to be able to be able to do that. How could I prevent this functionality?
[![enter image description here][1]][1]

Are you using AG Grid standalone or with Adaptable?
If you are using Adaptable also as we are then they have functions you can provide which will set whether or not the Column menu should appear in a given column.
See: https://docs.adaptabletools.com/guide/reference-options-menu#showadaptablecolumnmenu
And for Column Menus generally see: https://docs.adaptabletools.com/guide/ui-column-menu

Related

double click on nodes in cytoscape.js is not working

I have a problem with this plugin. I want to double click on nodes and the id of nodes should be displayed in console. I added the link of this extension from https://github.com/fixpoint/cytoscape-dblclick and followed by this post Cytoscape js - Call a function whenever a node is clicked, but still is not working.
Is anybody have any idea why it is not working, it would be nice if you share it.
You can see my code:
$(function() {
var elements = {
nodes: [
],
edges: [
]
};
function randomNumber(a) {
return Math.floor(Math.random() * (a));
}
var cy = window.cy = cytoscape({
container: document.getElementById('cy'),
ready: function() {},
style: [{
selector: "node", //edge
style: {
content: "data(id)",
shape: "roundrectangle", //square, circle
"text-valign": "center",
"text-halign": "center",
height: "60px", //new
width: "100px", //new
//padding: "10px", //new
"text-wrap": 'wrap', //new
color: "#fff",
"background-color": "#11479e",
// "background-color": "data(faveColor)"
}
},
{
//arrows
selector: "edge",
style: {
"curve-style": "taxi",
//'background-color': '#008000',
width: 4,
"target-arrow-shape": "triangle",
"line-color": "#9dbaea",
"target-arrow-color": "#9dbaea"
}
}
],
});
cy.dblclick();
cy.on('dblclick', function(evt) {
console.log('dblclick');
cy.animate({
fit: {
eles: evt.target,
padding: 10,
},
});
});
cy.on('dblclick:timeout', function(evt) {
console.log('dblclick:timeout');
});
var ab = 12;
for (var i = 0; i < ab; i++) {
//elements.nodes.push({ "data": { "id": i } });
cy.add([{
group: "nodes",
data: {
id: i
}
}
])
}
var cb = 20;
for (var i = 0; i < cb; i++) {
cy.add([{
group: "edges",
data: {
source: randomNumber(ab),
target: randomNumber(ab)
}
}])
}
cy.layout({
name: "dagre", //dagre, grid
directed: true,
nodeDimensionsIncludeLabels: true,
boxSelectionEnabled: true,
autounselectify: true,
zoomingEnabled: true,
userZoomingEnabled: true,
styleEnabled: true
}).run();
cy.elements().qtip({
content: function() {
return 'Text, Test ' + this.id()
},
position: {
my: 'center left', //top center
at: 'center right' //bottom center
},
style: {
classes: 'qtip-bootstrap', //qtip-dark
tip: {
width: 16,
height: 10
}
}
});
// });
}); //end
body {
font-family: helvetica;
font-size: 14px;
}
#cy {
width: 100%;
height: 100%;
position: absolute;
left: 0;
top: 0;
z-index: 999;
}
h1 {
opacity: 0.5;
font-size: 1em;
}
<!DOCTYPE>
<html>
<head>
<title>cytoscape-panzoom.js demo</title>
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1, maximum-scale=1">
<link href="cytoscape.js-panzoom.css" rel="stylesheet" type="text/css" />
<link href="font-awesome-4.0.3/css/font-awesome.css" rel="stylesheet" type="text/css" />
<script src="http://code.jquery.com/jquery-2.0.3.min.js"></script>
<script src="https://unpkg.com/cytoscape/dist/cytoscape.min.js"></script>
<!-- partial -->
<script src="https://js.cytoscape.org/js/cytoscape.min.js"></script>
<script src="https://cdn.rawgit.com/cpettitt/dagre/v0.7.4/dist/dagre.min.js"></script>
<script src="https://cdn.rawgit.com/cytoscape/cytoscape.js-dagre/1.5.0/cytoscape-dagre.js"></script>
<!-- qtip Links -->
<script src="https://unpkg.com/jquery#3.3.1/dist/jquery.js"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/qtip2/2.2.0/jquery.qtip.min.js"></script>
<link href="http://cdnjs.cloudflare.com/ajax/libs/qtip2/2.2.0/jquery.qtip.min.css" rel="stylesheet" type="text/css" />
<script src="https://cdn.rawgit.com/cytoscape/cytoscape.js-qtip/2.7.0/cytoscape-qtip.js"></script>
<!-- for testing with local version of cytoscape.js -->
<!-- <script src="../cytoscape.js/build/cytoscape.js"></script> -->
<script src="https://unpkg.com/cytoscape-dblclick/dist/index.js"></script>
<script src="cytoscape-panzoom.js"></script>
</head>
<body>
<div id="cy"></div>
</body>
</html>
Just follow the post you already linked and log the node information instead of fitting the graph to the clicked node. Also, your demo had some static scripts in the header, I removed them for that reason. That way, the qtip works again too:
$(function() {
var elements = {
nodes: [
],
edges: [
]
};
function randomNumber(a) {
return Math.floor(Math.random() * (a));
}
var cy = window.cy = cytoscape({
container: document.getElementById('cy'),
ready: function() {},
style: [{
selector: "node", //edge
style: {
content: "data(id)",
shape: "roundrectangle", //square, circle
"text-valign": "center",
"text-halign": "center",
height: "60px", //new
width: "100px", //new
//padding: "10px", //new
"text-wrap": 'wrap', //new
color: "#fff",
"background-color": "#11479e",
// "background-color": "data(faveColor)"
}
},
{
//arrows
selector: "edge",
style: {
"curve-style": "taxi",
//'background-color': '#008000',
width: 4,
"target-arrow-shape": "triangle",
"line-color": "#9dbaea",
"target-arrow-color": "#9dbaea"
}
}
],
});
cy.dblclick();
cy.on('dblclick', function(evt) {
console.log(evt.target.id());
});
var ab = 12;
for (var i = 0; i < ab; i++) {
//elements.nodes.push({ "data": { "id": i } });
cy.add([{
group: "nodes",
data: {
id: i
}
}
])
}
var cb = 20;
for (var i = 0; i < cb; i++) {
cy.add([{
group: "edges",
data: {
source: randomNumber(ab),
target: randomNumber(ab)
}
}])
}
cy.layout({
name: "dagre", //dagre, grid
directed: true,
nodeDimensionsIncludeLabels: true,
boxSelectionEnabled: true,
autounselectify: true,
zoomingEnabled: true,
userZoomingEnabled: true,
styleEnabled: true
}).run();
cy.elements().qtip({
content: function() {
return 'Text, Test ' + this.id()
},
position: {
my: 'center left', //top center
at: 'center right' //bottom center
},
style: {
classes: 'qtip-bootstrap', //qtip-dark
tip: {
width: 16,
height: 10
}
}
});
// });
}); //end
body {
font-family: helvetica;
font-size: 14px;
}
#cy {
width: 100%;
height: 100%;
position: absolute;
left: 0;
top: 0;
z-index: 999;
}
h1 {
opacity: 0.5;
font-size: 1em;
}
<!DOCTYPE>
<html>
<head>
<title>cytoscape-panzoom.js demo</title>
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1, maximum-scale=1">
<!--<link href="cytoscape.js-panzoom.css" rel="stylesheet" type="text/css" />-->
<!--<link href="font-awesome-4.0.3/css/font-awesome.css" rel="stylesheet" type="text/css" />-->
<script src="http://code.jquery.com/jquery-2.0.3.min.js"></script>
<script src="https://unpkg.com/cytoscape/dist/cytoscape.min.js"></script>
<!-- partial -->
<script src="https://js.cytoscape.org/js/cytoscape.min.js"></script>
<script src="https://cdn.rawgit.com/cpettitt/dagre/v0.7.4/dist/dagre.min.js"></script>
<script src="https://cdn.rawgit.com/cytoscape/cytoscape.js-dagre/1.5.0/cytoscape-dagre.js"></script>
<!-- qtip Links -->
<script src="https://unpkg.com/jquery#3.3.1/dist/jquery.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/qtip2/2.2.0/jquery.qtip.min.js"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/qtip2/2.2.0/jquery.qtip.min.css" rel="stylesheet" type="text/css" />
<script src="https://cdn.rawgit.com/cytoscape/cytoscape.js-qtip/2.7.0/cytoscape-qtip.js"></script>
<!-- for testing with local version of cytoscape.js -->
<!-- <script src="../cytoscape.js/build/cytoscape.js"></script> -->
<script src="https://unpkg.com/cytoscape-dblclick/dist/index.js"></script>
<!--<script src="cytoscape-panzoom.js"></script>-->
</head>
<body>
<div id="cy"></div>
</body>
</html>

Cytoscape.js: Overlapping edge labels in multigraph

There are several posts about edge or edge label overlaps in Cytoscape.js but the answers given there, like smaller labels and more spaced out nodes, don't help for a multigraph, i.e. a graph where two nodes can have multiple edges between them.
Is there a way to spread out edge labels even if they all belong to edges between the same two nodes? The edge pairs occur both in the same direction and in the reverse one.
As my graph is verly large, I would prefer a solution with haystack edges as the performance is already low.
Well you can rotate the text with "text-rotation": "autorotate" in the labels css. You can also define the "text-margin-x/y" for each node itself, but how do you plan on defining the position for each and every label? Lets assume, you did that perfectly: you would still need to do a reposition event after moving just one node, because the offsets will be off by then:
var cy = (window.cy = cytoscape({
container: document.getElementById("cy"),
boxSelectionEnabled: false,
autounselectify: true,
style: [{
selector: "node",
css: {
content: "data(id)",
"text-valign": "center",
"text-halign": "center",
height: "60px",
width: "60px",
"border-color": "black",
"border-opacity": "1",
"border-width": "10px"
}
},
{
selector: "$node > node",
css: {
"padding-top": "10px",
"padding-left": "10px",
"padding-bottom": "10px",
"padding-right": "10px",
"text-valign": "top",
"text-halign": "center",
"background-color": "#bbb"
}
},
{
selector: "edge",
css: {
"target-arrow-shape": "triangle"
}
},
{
selector: "edge[label]",
css: {
"label": "data(label)",
"text-rotation": "autorotate",
"text-margin-x": "data(xalign)",
"text-margin-y": "data(yalign)"
}
},
{
selector: ":selected",
css: {
"background-color": "black",
"line-color": "black",
"target-arrow-color": "black",
"source-arrow-color": "black"
}
}
],
layout: {
name: "circle"
}
}));
var info = [{
name: "Peter",
next_op_name: "Claire"
},
{
name: "Claire",
next_op_name: "Mike"
},
{
name: "Mike",
next_op_name: "Rosa"
},
{
name: "Rosa",
next_op_name: "Peter"
}
];
cy.ready(function() {
var array = [];
// iterate over info once
for (var i = 0; i < info.length; i++) {
array.push({
group: "nodes",
data: {
id: info[i].name, // id is name!!!
label: info[i].name
}
});
array.push({
group: "edges",
data: {
id: "e" + i,
source: info[i].name,
target: info[i].next_op_name,
label: "e" + i,
xalign: (i == 0 || i == 1 ? '15px' : '-15px'),
yalign: (i == 0 || i == 3 ? '15px' : '-15px')
}
});
}
cy.add(array);
cy.layout({
name: "circle"
}).run();
});
cy.on("mouseover", "node", function(event) {
var node = event.target;
node.qtip({
content: "hello",
show: {
event: event.type,
ready: true
},
hide: {
event: "mouseout unfocus"
}
},
event
);
});
cy.on("tapdrag", "node", function(event) {
// update all relevant labels
var labels = event.target.connectedEdges();
for (var i = 0; i < labels.length; i++) {
// render with the right positions?
}
});
body {
font: 14px helvetica neue, helvetica, arial, sans-serif;
}
#cy {
height: 100%;
width: 75%;
position: absolute;
left: 0;
top: 0;
float: left;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<html>
<head>
<meta charset=utf-8 />
<meta name="viewport" content="user-scalable=no, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, minimal-ui">
<script src="https://cdnjs.cloudflare.com/ajax/libs/cytoscape/3.2.17/cytoscape.min.js"></script>
<!-- qtip imports -->
<script src="https://unpkg.com/jquery#3.3.1/dist/jquery.js"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/qtip2/2.2.0/jquery.qtip.min.js"></script>
<link href="http://cdnjs.cloudflare.com/ajax/libs/qtip2/2.2.0/jquery.qtip.min.css" rel="stylesheet" type="text/css" />
<script src="https://cdn.rawgit.com/cytoscape/cytoscape.js-qtip/2.7.0/cytoscape-qtip.js"></script>
<!-- dagre imports -->
<script src="https://unpkg.com/dagre#0.7.4/dist/dagre.js"></script>
<script src="https://cdn.rawgit.com/cytoscape/cytoscape.js-dagre/1.5.0/cytoscape-dagre.js"></script>
</head>
<body>
<div id="cy"></div>
</body>
</html>
The problem breaks down to this: the task seems simple, but keeping track of the positions of all nodes and the edges aaaaand your rendered labels is a sisyphean task.

Fix animated images on slide

I'm trying to make an animation when changing a slide. The old slide disappears with the animation, and the new one shows up with the animation. My animation is alternating. Help. Thank you all !!
var app = new Vue({
el: '#app',
data() {
return {
selectedIndex: 0,
message: "Test work vue",
isOpenSlide: true,
startVal: 0,
decimals: 0,
duration: 2.5,
options: {
useEasing: true,
useGrouping: true,
separator: ',',
decimal: '.',
prefix: '',
suffix: ''
},
items: [
{
title: 'Center of osteopatia and rehabilitation',
url_img: 'https://i.imgur.com/gQp3VSW.jpg',
info_block: [
{
incremental: '800',
description: 'Increasing the number of transactions from organic search results'
},
{
incremental: '240',
description: 'Raising your revenue'
}
]
},
{
title: 'SLide 2',
url_img: 'https://newevolutiondesigns.com/images/freebies/space-wallpaper-5.jpg',
info_block: [
{
incremental: '140',
description: 'Increasing the numb organic search results'
},
{
incremental: '790',
description: 'Raising your revenue'
}
]
},
{
title: ' SLIDE 3',
url_img: 'https://www.planwallpaper.com/static/images/4433836-space-wallpapers.jpg',
info_block: [
{
incremental: '110',
description: 'Increasing the number of trans'
},
{
incremental: '99',
description: 'Raising your revenue'
}
]
}
]
}
},
methods: {
select(index) {
this.selectedIndex = index
},
index_dotnav: function (index) {
this.selectedIndex = index
},
open() {
this.isOpenSlide = true;
},
close() {
this.isOpenSlide = false;
},
toggle() {
if (this.isOpenSlide) {
this.close();
} else {
this.open();
}
},
ChangeSlider() {
setTimeout(() => {
if (++this.selectedIndex === this.items.length) {
this.selectedIndex = 0;
}
this.toggle();
this.ChangeSlider()
}, 5000)
},
callback(instance) {
instance.start();
}
},
mounted() {
this.ChangeSlider();
}
})
.slide-leave-active,
.slide-enter-active {
transition: 1s;
}
.slide-enter {
transform: translate(100%, 0);
}
.slide-leave-to {
transform: translate(-100%, 0);
}
ul {
padding-left: 0;
margin: 0;
}
.img-block,
section > *,
.uk-slideshow,
.uk-slideshow > ul {
height: 100vh !important;
}
.information-slide .uk-container {
position: absolute;
z-index: 1;
top: 0;
bottom: 0;
right: 0;
left: 0;
margin: auto 0;
display: flex;
flex-direction: column;
justify-content: center;
color: #fff;
}
.slideshow > div.dotnav-block {
top: 50%;
left: 95%;
z-index: 2;
}
.slideshow > div.dotnav-block li a {
background: #fff;
}
.slideshow > div.dotnav-block li.active a {
width: 13px;
height: 13px;
}
.slideshow > div.dotnav-block ul {
align-items: center;
}
.slideshow .slideshow-items > li {
display: none;
}
.slideshow .slideshow-items > li.active {
display: block;
position: relative;
}
.slideshow .slideshow-items > li img {
height: 100%;
width: auto;
object-fit: cover;
}
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/uikit/3.0.0-rc.14/css/uikit.min.css"/>
<body>
<div id="app">
<section>
<div class="uk-child-width-1-2" uk-grid>
<div>
<h1>{{ message }}</h1>
</div>
<div>
<div id="slideshow">
<div class="slideshow">
<ul class="slideshow-items">
<li v-for="(item,index) in items" :class="{'active':index===selectedIndex}"
v-on:click="select(index)">
<div class="information-slide">
<transition name="slide">
<div class="img-block" v-show="isOpenSlide">
<img v-bind:src="item.url_img" alt="">
</div>
</transition>
<div class="uk-container">
<div class="title title-1">{{item.title}}</div>
<div class="info-block">
<div class="info" v-for="(iblock,ind) in item.info_block">
<div class="incremental">
<span>+</span>
<!--<app-count-up-->
<!--:startVal="startVal"-->
<!--:endVal="iblock.incremental"-->
<!--:decimals="decimals"-->
<!--:duration="duration"-->
<!--:options="options"-->
<!--:callback="onReady"></app-count-up>-->
<span>%</span>
</div>
<div class="description descr-1">{{iblock.description}}</div>
</div>
</div>
</div>
</div>
</li>
</ul>
<div class="dotnav-block uk-position-bottom-center uk-position-small">
<ul class="uk-dotnav uk-dotnav-vertical">
<li :class="{'active':index===selectedIndex}" v-for="(item,index) in items"
v-on:click="index_dotnav(index)">
Item {{index}}</li>
</ul>
</div>
</div>
</div>
</template>
</div>
</div>
</section>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue#2.5.17/dist/vue.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/uikit/3.0.0-rc.14/js/uikit.min.js"></script>

How to add a permanent label within the React-Select input?

How could I extend React Select to permanently display an input label within the input? Here's a rough mockup:
Note, I don't want to use the 'placeholder' prop, because I want this label to display even after a value is set.
You could do it by setting the placeholder to an empty value and creating a pseudo :before element in CSS:
class App extends React.Component {
state = {
value: [],
}
handleChange = (value) => {
this.setState({ value });
}
render() {
return (
<Select
className="my-react-select"
multi
onChange={this.handleChange}
options={[
{ value: 'caramel', label: 'Caramel' },
{ value: 'chocolate', label: 'Chocolate' },
{ value: 'vanilla', label: 'Vanilla' },
{ value: 'mudcake', label: 'Mudcake' },
]}
placeholder=""
value={this.state.value}
/>
);
}
}
ReactDOM.render(<App />, document.getElementById('root'));
#root {
font-family: sans-serif;
max-width: 400px;
}
.my-react-select .Select-control:before {
color: #aaa;
content: 'Flavors';
line-height: 34px;
padding-left: 10px;
padding-right: 10px;
position: absolute;
}
.my-react-select .Select-placeholder + .Select-input,
.my-react-select .Select-input:first-child,
.my-react-select .Select-value:first-child {
margin-left: 70px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<script src="https://unpkg.com/prop-types#15.5.10/prop-types.js"></script>
<script src="https://unpkg.com/classnames#2.2.5/index.js"></script>
<script src="https://unpkg.com/react-input-autosize#2.0.0/dist/react-input-autosize.js"></script>
<script src="https://unpkg.com/react-select/dist/react-select.js"></script>
<link rel="stylesheet" href="https://unpkg.com/react-select/dist/react-select.css">
<div id="root"></div>

Vue js get parent property AFTER it's ready method has ran

I know I can use inherit to allow a child component to grab it's parent's properties, BUT the thing is.. is that I need to grab the property AFTER the parent ready method has ran. I'm having this issue everywhere in order to get width and height of parent components that are set in the ready method.
var Carousel = Vue.component('carousel', {
template: '#carousel',
replace: true,
data: function() {
return {
current: 1,
slideWidth: 600,
count: 6,
style: {
width: 600,
viewport: 600,
marginLeft: 0
}
}
},
computed: {
styles: function() {
return {
width: this.style.width + 'px',
marginLeft: this.style.marginLeft + 'px'
}
},
viewport: function() {
return {
width: this.style.viewport + 'px'
}
},
rounds: Math.floor(this.count / this.show)
},
props: ['show', 'slideMargin'],
ready: function() {
this.slideWidth = $(this.$el).width();
this.count = this.$children.length;
this.style.width = (this.slideWidth * this.count) + (this.slideMargin * (this.count * 2));
this.style.viewport = (this.slideWidth * this.show) + (this.slideMargin * (this.show * 2));
}
});
var CarouselSlide = Vue.component('carouselslide', {
template: '#slide',
replace: true,
data: function() {
return {
style: {
width: 200
}
}
},
computed: {
styles: function() {
return {
width: this.style.width + 'px'
}
}
},
ready: function() {
this.style.width = this.$parent.$get('slideWidth');
}
});
new Vue({
el: '#testimonials'
});
#testimonials {
width: 50%;
margin: 0 auto;
position: relative;
float: left;
min-height: 1px;
padding-left: 1.25rem;
padding-right: 1.25rem;
display: block;
}
h3 {
color: #b50937;
text-transform: uppercase;
margin: 0 0 20px;
font-size: 1.75rem;
}
.carousel {
position: relative;
overflow: hidden;
}
.carousel .slides {
overflow: hidden;
margin: 0 auto;
}
.carousel .slides .viewport {
overflow: hidden;
-webkit-transform: translateZ(0);
transform: translateZ(0);
transition: all 800ms cubic-bezier(0.77, 0, 0.175, 1);
transition-timing-function: cubic-bezier(0.77, 0, 0.175, 1);
}
.carousel .slides .slide {
position: relative;
display: block;
float: left;
margin: 0 2px;
}
.carousel .slides .slide .box {
background-color: #d1dbe5;
box-sizing: border-box;
padding: 15px 20px;
}
.view-all {
text-align: right;
}
.arrows {
position: relative;
text-align: right;
width: 100%;
}
.arrows .arrow {
background-color: #d3d3d3;
color: #fff;
padding: 2px 13px;
position: static;
transition: 0.4s ease-in-out;
display: inline-block;
cursor: pointer;
}
<link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.4.0/css/font-awesome.min.css" rel="stylesheet"/>
<script src="http://cdnjs.cloudflare.com/ajax/libs/vue/0.12.13/vue.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script type="x-template" id="carousel">
<div class="carousel">
<div class="slides" v-style="viewport">
<div class="viewport" v-style="styles">
<content></content>
</div>
</div>
<div class="view-all">View all <i class="fa fa-angle-double-right"></i></div>
<div class="arrows">
<div class="arrow prev" v-on="click: prevSlide"><i class="fa fa-chevron-left"></i></div>
<div class="arrow next" v-on="click: nextSlide"><i class="fa fa-chevron-right"></i></div>
</div>
</div>
</script>
<script type="x-template" id="slide">
<div class="slide" v-style="styles">
<content></content>
</div>
</script>
<section id="testimonials">
<h3>What People Are Saying About Us</h3>
<carousel show="1" slide-margin="2">
<carouselslide>
<div class="phrase">
<div class="box">
We were looking to upgrade our equipment when we came across Ventrac. It was "wow" for
us, why did we suffer for the first six years with these other pieces of equipment when we could of had this.
</div>
</div>
</carouselslide>
<carouselslide>
<div class="phrase">
<div class="box">
We were looking to upgrade our equipment when we came across Ventrac. It was "wow" for
us, why did we suffer for the first six years with these other pieces of equipment when we could of had this.
</div>
</div>
</carouselslide>
</carousel>
</section><!-- END #TESTIMONIALS -->
Here is my Vue code since it's the only part that's relevant, although you can see what I'm having issues with upstairs ^^ (the snippet)
var Carousel = Vue.component('carousel', {
template: '#carousel',
replace: true,
data: function() {
return {
current: 1,
slideWidth: 600,
count: 6,
style: {
width: 600,
viewport: 600,
marginLeft: 0
}
}
},
computed: {
styles: function() {
return {
width: this.style.width + 'px',
marginLeft: this.style.marginLeft + 'px'
}
},
viewport: function() {
return {
width: this.style.viewport + 'px'
}
},
rounds: Math.floor(this.count / this.show)
},
props: ['show', 'slideMargin'],
ready: function() {
this.slideWidth = $(this.$el).width();
this.count = this.$children.length;
this.style.width = (this.slideWidth * this.count) + (this.slideMargin * (this.count * 2));
this.style.viewport = (this.slideWidth * this.show) + (this.slideMargin * (this.show * 2));
}
});
var CarouselSlide = Vue.component('carouselslide', {
template: '#slide',
replace: true,
data: function() {
return {
style: {
width: 200
}
}
},
computed: {
styles: function() {
return {
width: this.style.width + 'px'
}
}
},
ready: function() {
this.style.width = this.$parent.$get('slideWidth');
}
});
new Vue({
el: '#testimonials'
});
The reason I need to get it from the parent is because the clientWidth includes padding which I can't. So I can't do $(this.$el).width() in the data or computed properties data since $el is not available yet. From my child, I need to get this width AFTER the ready method has fired.
Thanks for any insight.
Without looking too closely at your code, my first thought to get parent data in the child is:
computed: {
val: this.$parent.val;
}
But I'm not certain that will work for you. Alternatively you might be able to change your parent's ready method to compiled so it runs before the child.