I am making an application where I have multi select dropdown..
In which there is a requirement that I need to place the selected items below the select container.
Working Snippet:
#container {
position: relative;
text-align: left;
width:100%;
}
#container > div {
padding-top: 2em;
}
._2iA8p44d0WZ {
border: 1px solid #cccccc;
border-radius: 4px;
padding: 5px;
min-height: 22px;
position: relative;
}
._7ahQImy {
padding: 4px 10px;
background: #0096fb;
margin-right: 5px;
margin-bottom: 5px;
border-radius: 10px;
display: inline-flex;
align-items: center;
font-size: 13px;
color: #fff;
white-space: nowrap;
}
#search_input {
position: absolute;
top: 0;
left: 0;
}
<div id="container">
<div class="_2iA8p44d0WZ">
<span class="chip _7ahQImy">This is the main label</span>
<span class="chip _7ahQImy false false">secondary label</span>
<span class="chip _7ahQImy">Another label</span>
<span class="chip _7ahQImy false false">even more labels labels labels labels labels labels</span>
<input type="text" class="searchBox" id="search_input" placeholder="Select" autocomplete="off" value="">
</div>
</div>
The above one provides the result of making the selected items and select box inside a container.
Expected Output
|------ (#container) Start -----|
| --------------------- |
| | Search Input | |
| --------------------- |
| |
|------ (#container) End -------|
| This is the main label |
| secondary label |
| Another label |
| even more labels labels labels labels labels labels |
Note:
-> I cannot modify any of the HTML elements given.
-> There are some dynamic classes inside it for which I cannot modify the css classes for those dynamic classes.
-> List of dynamic classes for which css properties cannot be modified, _2iA8p44d0WZ and _7ahQImy .
-> List of ids/classes, I can modify the css properties are #container and .chip (span).
The exact library that I am trying to modify in my real app is here along with css code,
Please help me to place the selected items below the container box as like the above given expected result.
You can hide the internal chips of the multi-select using the style prop.
CSS Customization
style={{
chips: {
display: 'none',
}
}}
Now you need to render your selectedValues outside the Multiselect component. In order to do this you need to update your state.selectedValues state array, and map state.selectedValues to your own custom chip components.
Add an onSelect callback.
onSelect={(selectedValues) => this.setState({ selectedValues })}
Map state.selectedValues to "chips". I used a span, but you can use any wrapping element and style it accordingly.
<div>
{selectedValues.map((chip) => (
<span>{chip.key}</span>
))}
</div>
Fullcode
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
plainArray: ["Option 1", "Option 2", "Option 3", "Option 4", "Option 5"],
objectArray: [
{ key: "Option 1", cat: "Group 1" },
{ key: "Option 2", cat: "Group 1" },
{ key: "Option 3", cat: "Group 1" },
{ key: "Option 4", cat: "Group 2" },
{ key: "Option 5", cat: "Group 2" },
{ key: "Option 6", cat: "Group 2" },
{ key: "Option 7", cat: "Group 2" }
],
selectedValues: [
{ key: "Option 1", cat: "Group 1" },
{ key: "Option 2", cat: "Group 1" }
]
};
this.style = {
chips: {
background: "red"
},
searchBox: {
border: "none",
"border-bottom": "1px solid blue",
"border-radius": "0px"
},
multiselectContainer: {
color: "red"
}
};
}
render() {
const { objectArray, selectedValues } = this.state;
return (
<div className="App">
<h4 id="checkbox" className="mt40 mx20">
<b>
{" "}
How can I customize the css for below below multi select to display
only select box inside container and selected items after container
box?{" "}
</b>
</h4>
<Multiselect
options={objectArray}
displayValue="key"
onSelect={(selectedValues) => this.setState({ selectedValues })}
showCheckbox={true}
selectedValues={selectedValues}
style={{
chips: {
display: "none"
}
}}
/>
<div>Some Content</div>
<div>Some More Content</div>
<div>
Selected Values:
{selectedValues.map((chip) => (
<span>{chip.key}</span>
))}
</div>
</div>
);
}
}
Edit
To enable removing selected items then also implement the onRemove callback. To duplicate the chip style copy the applied chip CSS rules to your own style object.
const styles = {
chip: {
padding: "4px 10px",
background: "#0096fb",
marginRight: "5px",
marginBottom: "5px",
borderRadius: "10px",
display: "inline-flex",
alignItems: "center",
fontSize: "13px",
color: "#fff",
whiteSpace: "nowrap"
}
};
Also start with empty selected state
this.state = {
plainArray: ["Option 1", "Option 2", "Option 3", "Option 4", "Option 5"],
objectArray: [
{ key: "Option 1", cat: "Group 1" },
{ key: "Option 2", cat: "Group 1" },
{ key: "Option 3", cat: "Group 1" },
{ key: "Option 4", cat: "Group 2" },
{ key: "Option 5", cat: "Group 2" },
{ key: "Option 6", cat: "Group 2" },
{ key: "Option 7", cat: "Group 2" }
],
selectedValues: []
};
...
<Multiselect
options={objectArray}
displayValue="key"
onSelect={(selectedValues) => this.setState({ selectedValues })}
onRemove={(selectedValues) => this.setState({ selectedValues })} // <-- implement
showCheckbox={true}
selectedValues={selectedValues}
style={{
chips: {
display: "none"
}
}}
/>
...
<div>
Selected Values:
{selectedValues.map((chip) => (
<span key={chip.key} style={styles.chip}> // <-- set chip style prop
{chip.key}
</span>
))}
</div>
Related
I am new to Vue.js and for this project, I am using Vuedraggable to drag items. Currently, the items inside the draggabble div are displayed as
Text 1
Text 2
Text 3
Text 4
Is there a way we can change that and display as
Text 1 Text 2
Text 3 Text 4
JsFiddle Link = https://jsfiddle.net/ujjumaki/y1xw95rc/41/
View
<div id="app">
<div>
<draggable id="first" data-source="juju" :list="todos" class="list-group" draggable=".item">
<div class="list-group-item item" v-for="(element, index) in todos" :key="index" style="border-style: outset;
margin-top:0.5%; width: 10%; border-color:#17a2b8; border-width:thin;">
<p>
{{element.text}} id {{element.id}}
</p>
</div>
</draggable>
</div>
</div>
<script src="//cdnjs.cloudflare.com/ajax/libs/vue/2.5.2/vue.min.js"></script>
<script src="//cdn.jsdelivr.net/npm/sortablejs#1.8.4/Sortable.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/Vue.Draggable/2.20.0/vuedraggable.umd.min.js"></script>
Method
new Vue({
el: "#app",
data: {
todos: [
{ text: "Text 1", id: "1" },
{ text: "Text 2", id: "2" },
{ text: "Text 3", id: "3"},
{ text: "Text 4", id: "4" }
]
},
methods: {
toggle: function(todo){
todo.done = !todo.done
}
}
})
Try to add following css:
#first {
display: grid;
grid-template-columns: 1fr 1fr;
justify-items: center;
text-align: center;
}
.list-group-item {
width: 100% !important;
}
Is there's any way to bind multiple checkboxes from many children to one parent (f.e. via model)?
Let's say that the child component has something like:
<input
type="checkbox"
:id="'ticket-'+id"
:checked="checked"
/>
Now, is it possible to have a parent prop like selected that would collect the id as values in an array of all checked checkboxes from children?
{
selected: [
5,
8
]
}
The nearest thing to my solution in mind is this. But in my case, I don't want to keep track of unchecked instances.
You can listen to the checkbox change events on the parent and call a method which updates the data model.
Check out the fiddle below demonstrating this. (Go full page to see it properly)
new Vue({
el: "#app",
data: {
list: [
{ id: 1, label: 'Check 1'},
{ id: 2, label: 'Check 2'},
{ id: 3, label: 'Check 3'},
{ id: 4, label: 'Check 4'},
],
selected: []
},
methods: {
handleChange: function(ev) {
let id = ev.target.id;
if (ev.target.checked) {
if (!this.selected.includes(id)) {
this.selected.push(id);
}
} else {
this.selected = this.selected.filter(function (item) {
return item !== id;
});
}
console.log('Updated: ', this.selected);
}
}
})
body {
background: #20262E;
padding: 20px;
font-family: Helvetica;
}
#app {
background: #fff;
border-radius: 4px;
padding: 20px;
transition: all 0.2s;
}
li {
margin: 8px 0;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.16/vue.js"></script>
<div id="app">
<ol #change="handleChange">
<li v-for="check in list">
<label>
<input type="checkbox" :id="check.id" />
<span>{{check.label}}</span>
</label>
</li>
</ol>
</div>
I have 2 Vuetify data tables without pagination. Every row of the second one got exactly one parent in the first one. If I click on one of those entries in the second one, I want to search for the parent and jump to that row. All I found for now is filtering, but I only want to have that row on top of my table.
Is something like this possible?
We can't really help you without code, even if i've seen that you can't, it should be cool if you could modify some parts of your code like variables and datas ...
However, i'll try to do my best to explain
What you have to do is to reorder your data array binded on your table depending on a given id (or other data) to identify it.
I made a similar exemple of your needs, but i repeat i can't really be exhausitve :
Parent component:
<template>
<div id="app">
<listone :list="listOne" :toggled="toggledParent"></listone>
<listtwo :list="listTwo" v-model="toggledParent"></listtwo>
</div>
</template>
<script>
export default {
name: "App",
data: () => ({
toggledParent: 0,
listOne: [
{
id: 1,
title: "parent1",
},
{
id: 2,
title: "parent2",
},
{
id: 3,
title: "parent3",
},
],
listTwo: [
{
title: "title1",
parent: 3,
},
{
title: "title2",
parent: 1,
},
{
title: "title3",
parent: 2,
},
],
}),
components: {
listone: () => import("#/components/listone"),
listtwo: () => import("#/components/listtwo"),
},
};
</script>
<style>
#app {
font-family: "Avenir", Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
display: flex;
flex-flow: row nowrap;
justify-content: space-between;
}
</style>
ListOne component :
<template>
<div class="list">
<a v-for="item in treatedList" :key="item.title">
{{ item.title }}
</a>
</div>
</template>
<script>
export default {
name: "listone",
props: {
list: Array,
toggled: Number,
},
computed: {
treatedList: function () {
let tmp = this.list;
let $this = this
return tmp.sort(function (a, b) {
return a.id === $this.toggled ? -1 : b.id === $this.toggled ? 1 : 0;
});
},
},
};
</script>
<style>
.list {
display: flex;
flex-flow: column nowrap;
}
.list > a {
border: 1px solid red;
}
</style>
ListTwo component :
<template>
<div class="list">
<a
v-for="item in list"
:key="item.title"
#click="$emit('input', item.parent)">
{{ item.title }}
</a>
</div>
</template>
<script>
export default {
name: "listtwo",
props: {
list: Array,
toggledParent: Number
},
};
</script>
<style scoped>
.list {
display: flex;
flex-flow: column nowrap;
}
.list > a {
border: 1px solid red;
}
</style>
Try it and say me it helps you as wanted
Demo on codesandbox.io : https://codesandbox.io/s/mutable-thunder-zo8vn?fontsize=14&hidenavigation=1&theme=dark
So without knowing what your data looks like i'll use a standard array of objects without meta data.
What you could do, is use the sort function inside of computed property like below, this will re-organize your list every time you match or filter the list.
(Note: This re-arranges your entire list every time)
Here is a really basic example:
new Vue({
el: "#app",
data: {
search: 'Bananas',
tableData: [
{
item: "Cherries",
price: 3.99,
type: "Fruit"
},
{
item: "Chicken",
price: 6.99,
type: "Meat"
},
{
item: "Bananas",
price: 1.99,
type: "Fruit"
},
{
item: "Cola",
price: 0.99,
type: "Drink"
},
{
item: "Coffee",
price: 2.99,
type: "Drink"
},
]
},
computed: {
getTableData: function() {
return this.tableData.sort((x,y) => { return x.item == this.search ? -1 : y.item == this.search ? 1 : 0; });
}
}
})
table {
background: #ccc;
padding: 20px;
width:50%;
}
table tr {
background: #f1f1f1;
}
table tr td {
padding: 10px;
}
.firstRow {
background: green;
color:white;
}
.searchBar {
padding:20px;
width: 40%;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<div class="searchBar">
Search <input type="text" v-model="search">
</div>
<table>
<tr class="firstRow"><td>Item</td> <td>Price</td> <td>Type</td></tr>
<tr v-for="(product, index) in getTableData" :key="index">
<td>{{product.item}}</td>
<td>{{product.type}}</td>
<td>{{product.price}}</td>
</tr>
</table>
</div>
I have used Jquery Kendo Dropdownlist , to display information in list. Here my requirement is to add the bellow mention styles i.e. (.k-list-container and .k-list-scroller ) to Dropdownlist using JavaScript.
And make the height of ".k-list-scroller" dynamic i.e. the drop down list-area when selected, the height of it, should go beyond screen height or window height. In this case i have hard coded (height: 500px !important;).
.k-list-container{
width: auto !important;
height: auto !important;
}
.k-list-scroller{
height: 500px !important;
overflow-y: scroll !important;
}
The bellow code example is for reference -
<style>
.k-list
{
white-space: nowrap;
}
.k-list-container{
width: auto !important;
height: auto !important;
}
.k-list-scroller{
height: 500px !important;
overflow-y: scroll !important;
}
</style>
<div id="example">
<p>
data: <select id="local"></select>
</p>
</div>
<script>
$(function() {
var data = [
{ text: "Grey Grey Grey Grey Grey Grey Grey Grey Grey Grey Grey Grey Grey Grey Grey Grey Grey ", value: "13" },
{ text: "Black 1", value: "1" },
{ text: "Orange 2", value: "2" },
{ text: "Black 3", value: "3" },
{ text: "Orange 4", value: "4" },
{ text: "Black 5", value: "5" },
{ text: "Orange 6", value: "6" },
{ text: "Black 7", value: "7" },
{ text: "Orange 8", value: "8" },
{ text: "Black 9", value: "9" },
{ text: "Orange 10", value: "10" },
{ text: "Black 11", value: "11" },
{ text: "Orange 12", value: "12" }
];
$("#local").kendoDropDownList({
dataTextField: "text",
dataValueField: "value",
dataSource: data,
});
});
</script>
Thanks.
You can add a class to the element created by $("#local").kendoDropDownList({}).
The created element has an id with a "-list" post-fix.
See the snippet for a demo:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8"/>
<title>Kendo UI Snippet</title>
<link rel="stylesheet" href="https://kendo.cdn.telerik.com/2019.1.220/styles/kendo.common.min.css"/>
<link rel="stylesheet" href="https://kendo.cdn.telerik.com/2019.1.220/styles/kendo.rtl.min.css"/>
<link rel="stylesheet" href="https://kendo.cdn.telerik.com/2019.1.220/styles/kendo.silver.min.css"/>
<link rel="stylesheet" href="https://kendo.cdn.telerik.com/2019.1.220/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.1.220/js/kendo.all.min.js"></script>
<style>
#dropdownlist-list.test-class .k-list {
white-space: nowrap;
}
#dropdownlist-list.test-class .k-list-container {
width: auto !important;
height: auto !important;
}
#dropdownlist-list.test-class .k-list-scroller {
//height: 500px !important; // Causes a UI glitch
overflow-y: scroll !important;
}
</style>
</head>
<body>
<button onclick="testFunction()">Test Button</button>
<br>
<input id="dropdownlist" />
<script>
var data = [
{ text: "Grey Grey Grey Grey Grey Grey Grey Grey Grey Grey Grey Grey Grey Grey Grey Grey Grey ", value: "13" },
{ text: "Black 1", value: "1" },
{ text: "Orange 2", value: "2" },
{ text: "Black 3", value: "3" },
{ text: "Orange 4", value: "4" },
{ text: "Black 5", value: "5" },
{ text: "Orange 6", value: "6" },
{ text: "Black 7", value: "7" },
{ text: "Orange 8", value: "8" },
{ text: "Black 9", value: "9" },
{ text: "Orange 10", value: "10" },
{ text: "Black 11", value: "11" },
{ text: "Orange 12", value: "12" }
];
$("#dropdownlist").kendoDropDownList({
dataSource: data,
dataTextField: "text",
dataValueField: "value"
});
function testFunction() {
$("#dropdownlist-list").addClass("test-class");
}
</script>
</body>
</html>
I have an array list in my hand, I want to show this array listi with the ng-repeat as in the image.
What's the right way to do this?
I want to do the following if possible, there are "+" on the four sides of the box. When I click on "+", in which way I click on it, I want new boxes to be created in that direction as much as the number of boxes under it. The other option is the delete icon in each box. I want that box erased when I click on them.
I want the visual in the image.
vm.sections = {
width: 3,
matrix: [
{ name: "Left Text", position: "left" },
{ name: "Top Text", position: "top" },
{ name: "Right Text", position: "right" },
{ name: "Left Text", position: "left" },
{ name: "Center", position: "center" },
{ name: "Right Text", position: "right" },
{ name: "Left Text", position: "left" },
{ name: "Bottom Text", position: "bottom" },
{ name: "Bottom Text", position: "bottom" }
]
};
<div class="table">
<div class="body">
<div class="row" ng-if="(section.position==='top' || section.position==='bottom' || section.position==='center')"
ng-repeat="section in sections.matrix track by $index">
<div class="cell section"
ng-repeat="section in sections.matrix track by $index">
{{ section.name }}
</div>
</div>
</div>
</div>