Ant Design Vue - Custom Header in Collapse Component - vue.js

Hello I'am using Vue and Ant Design. So i pick Collapse Component from Ant Design: https://antdv.com/components/collapse/
My problem is that in Collapse.Panel there is a prop header which is string, but i need to put string in there (example: v0.6.1.11) and date, so i can add margin-left: auto or something like that in date.
Exmaple:
I tried using white-space: pre and then simply add spaces to achive that space between but it's not responsive solution.
How can i pass into header prop pure html so i could put something like two <p> tags there and then create space between title and date?

As per docs, we can make use of Panel property extra slot.
Run this sample code
new Vue({
el: "#app",
data() {
return {
text: `A dog is a type of domesticated animal.Known for its loyalty and faithfulness,it can be found as a welcome guest in many households across the world.`,
activeKey: ['1'],
expandIconPosition: 'left',
};
},
computed:{
currDate(){
return new Date().toLocaleDateString()
}
}
});
.ant-collapse>.ant-collapse-item>.ant-collapse-header{
display:flex;
justify-content:space-between
}
<link rel="stylesheet" href="https://unpkg.com/ant-design-vue#1.4.11/dist/antd.min.css">
<script src="https://unpkg.com/vue#2.6.11/dist/vue.min.js"></script>
<script src="http://bms.test/vendor/laravel-admin/moment/min/moment-with-locales.min.js"></script>
<script src="https://unpkg.com/ant-design-vue#1.5.0/dist/antd.min.js"></script>
<div id="app">
<a-collapse v-model="activeKey">
<a-collapse-panel key="1" header="This is panel header 1">
<p>{{ text }}</p>
<div slot="extra">{{currDate}}</div>
</a-collapse-panel>
<a-collapse-panel key="2" header="This is panel header 2" :disabled="false">
<p>{{ text }}</p>
<div slot="extra">{{currDate}}</div>
</a-collapse-panel>
<a-collapse-panel key="3" header="This is panel header 3" disabled>
<p>{{ text }}</p>
<div slot="extra">{{currDate}}</div>
</a-collapse-panel>
</a-collapse>
</div>

You can use the below code for the pupose.
<a-collapse-panel key="1" header="heading 1">
<p>Content</p>
<template #extra><p>heading 2</p></template> <!-- for newer version -->
<p slot="extra">heading 2</p> <!-- for older version -->
</a-collapse-panel>

Related

How to show an empty row in BootstrapVue's b-table

I am using a b-table from BootstrapVue. However, when the array of objects for my table is empty, i want to show the table headers + 1 empty row, without any text in the cells of the table.
On BoostrapVue's b-table page, there is some explanation about showing something for an empty table, but i'm not following the explanation. There is also no visual of the outcome.
When using show-empty, it gives a simple text 'no records ...', but i don't want the text. Or maybe i want a custom text (depending on the language when using i18n).
So the html is currently:
<b-table bordered :head-variant="'light'" hover :items="dogs" :fields="dogHeaders" >
</b-table>
And in the vue data i have:
dogs: [], //because i want to mimic an empty table
dogHeaders: ['name','color','age'],
Can someone show me an example how to do this?
edit: i currently see only a workaround with populating my dogs array with an empty dog like so:
dogs: [{name:'',color:'',age:''}],
But i guess there should be a better way (+ this workaround gives a row that has less height than an actual filled row)
You could use b-table with show-empty attribute and slots. I prepared a code snippet to show this:
new Vue({
el: '#app',
data: {
dogs: [],
dogHeaders: ['name', 'color', 'age'],
}
})
<link href="https://unpkg.com/bootstrap-vue#2.21.2/dist/bootstrap-vue.css" rel="stylesheet" />
<link href="https://unpkg.com/bootstrap#5.0.0-beta3/dist/css/bootstrap.min.css" rel="stylesheet" />
<script src="https://unpkg.com/vue/dist/vue.min.js"></script>
<script src="https://unpkg.com/bootstrap-vue#2.21.2/dist/bootstrap-vue.js"></script>
<div id="app">
<b-table bordered :head-variant="'light'" hover :items="dogs" :fields="dogHeaders" show-empty>
<template #empty="scope">
Empty row
</template>
</b-table>
</div>
I think the example is right there in the docs. They provide slots for exactly this use case, where you can put anything you want:
<b-table bordered :head-variant="'light'" hover :items="dogs" :fields="dogHeaders" show-empty>
<template #empty="scope">
Whatever HTML you put here will be shown when the table is empty
</template>
</b-table>
Since you want to render actual cells, you can use the top-row slot instead of the standard empty slot.
You can then conditionally render the slot using a v-if, based on whether the dogs array is empty or not.
Then render empty cells (<td>) inside the slot for each element in your dogHeaders array.
new Vue({
el: '#app',
data() {
return {
dogs: [],
dogHeaders: ['name', 'color', 'age']
}
},
methods: {
addRow() {
this.dogs.push({
name: 'Pence',
color: 'Black',
age: 53
})
}
}
})
<link href="https://unpkg.com/bootstrap#4.5.3/dist/css/bootstrap.min.css" rel="stylesheet" />
<script src="https://unpkg.com/vue#2.6.12/dist/vue.min.js"></script>
<script src="https://unpkg.com/bootstrap-vue#2.21.2/dist/bootstrap-vue.js"></script>
<div id="app" class="p-3">
<b-btn #click="dogs = []">Reset Table</b-btn>
<b-btn #click="addRow">Add row</b-btn>
<hr />
<b-table bordered head-variant="light" hover :items="dogs" :fields="dogHeaders">
<template #top-row v-if="dogs.length === 0">
<!-- Adding to the cell so that it maintains the standard cell height -->
<td v-for="i in dogHeaders.length"> </td>
</template>
</b-table>
</div>

How to add a class and then remove that same class in the vuejs?

I have the following div:
<div class="col bg-color-red-4">
<a href="#" v-on:click="showMobileMenu = !showMobileMenu">
<i class="hamburger hamburger--3dx " v-bind:class="{ 'is-active': showMobileMenu }" >
<span class="hamburger-box">
<span class="hamburger-inner"></span>
</span>
</i>
</a>
<p>3DX</p>
</div>
data(){
return {
showMobileMenu: false
}
},
That is visually like this:
basically it's a button that allows me to open the left panel:
When you click on the button you add the class 'is-active' that allows the change of form, leaving it like this:
and it effectively opens the left panel, but after turning off the left panel, that is, returning to the view that I was in, this one finds the class added.
then I need that when I click, I change the shape to an "X", when I open the left panel, but when I come back I do not have the form "X", that is, it does not contain the class 'is-active' anymore
Beforehand thank you very much.
At first read the official docs:
[https://v2.vuejs.org/v2/guide/class-and-style.html#ad][1]
At second - check Matt Oestreich's answer
At third - you can also bind classes to the variables like this:
<div
class="static"
v-bind:class="{ active: isActive, 'text-danger': hasError }"
/>
And in a Vue.js script:
data: {
isActive: true,
hasError: false
}
You can bind to the class attribute and supply specific classes that way..
[CodePen Mirror]
Code Snippet:
const vm = new Vue({
el: "#app",
data: {
status: false,
bars: "fa fa-bars",
times: "fa fa-times",
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.6.10/vue.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vuetify/1.5.14/vuetify.min.js"></script>
<link href="https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900|Material+Icons" rel="stylesheet" />
<link href="https://cdn.jsdelivr.net/npm/font-awesome#4.7.0/css/font-awesome.min.css" rel="stylesheet" />
<link href="https://cdn.jsdelivr.net/npm/vuetify#1.5.6/dist/vuetify.min.css" rel="stylesheet" />
<div id="app">
<v-app>
<v-content>
<v-container>
<i
style="cursor:pointer;"
:class="status ? times : bars"
#click="status = !status"
></i>
<h1>Click The Icon</h1>
<h3>It is currently {{ status ? 'open' : 'closed' }}</h3>
</v-container>
</v-content>
</v-app>
</div>

vuejs render part of template inside different elements without repeating

I am new to Vuejs. This is what I need to do.
<div v-for="r in records">
<div v-if="r.something">
<div id="x">
{{ r. something}}
more of r here.
</div>
</div>
<div v-else id="x">
same div as in the block above.
</div>
</div>
What I want do is not define div with id x two times as it is huge.
Make your 'div' a component and refer to it in both places.
There are many ways to define your component. This is example shows just one. If you are using WebPack, use a single file component. You can then have your script, html, and css all in one file that gets precompiled. That's the best way to manage your 'huge' div. Then you can continue to refactor and break it up into more components.
const myComponent = {
template: "<div :id='id'>HELLO, my id is {{id}}. r.foo is {{r.foo}} </div>",
props: {
id: String
},
data() {
return {
r: {
foo: 'bar'
}
}
}
}
<div v-for="r in records">
<div v-if="r.something">
<my-component id='x' />
</div>
<div v-else id="x">
<my-component id='x' />
</div>
</div>

why is Vuejs disabling the ability of a media query to add and remove component

Given i have this
//mycompoent.js
Vue.component('main-nav',{
template:`
<div id="main-nav">
</div>
`
});
Vue.component('menu-nav',{
template:`
<div id="menu-nav">
</div>
`
});
new Vue({
}).$mount("#nav-app");
Then in my CSS I have the following
//style.css
#menu-nav{display:none;}
#media (max-width:840px){
#main-nav{display:none;}
#menu-nav{display:block;}
}
//index.html
<div id="nav-app">
<main-nav />
<menu-nav />
</div>
When I resize the browser less than 840px the menu-nav component never appears; I don't know what I have done wrong.
If you're testing this directly in the browser (without a compile step), you can't use the self-closing form <main-nav /> for components. Try the following:
<div id="nav-app">
<main-nav></main-nav>
<menu-nav></menu-nav>
</div>

Can't get the correct value of scrollHeight for a textarea - VueJs, Vuetify

Am trying to get the value scrollHeight of a texteara filed, the problem is when i use the document object : document.querySelector("#textarea-element").scrollHeight, i have a correct value ,
but when i’ve tried to do it with refs the value is wrong and didn’t change.
I’ve made a detailed jsfiddle for these behaviors please see below:
new Vue({
el: '#app' ,
data: {
height: 'auto',
scrollHeightUsingRefsVuejs:'',
scrollHeightUsingDocumentObject: ''
},
methods:{
resizeTextarea (e) {
this.scrollHeightUsingRefsVuejs = this.$refs.messageBox.$el.scrollHeight
this.scrollHeightUsingDocumentObject = document.querySelector("#textarea-element").scrollHeight
console.log(this.scrollHeightUsingRefsVuejs, this.scrollHeightUsingDocumentObject)
}
}
})
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<link href="https://unpkg.com/vuetify#1.0.11/dist/vuetify.min.css" rel="stylesheet"/>
<script src="https://unpkg.com/vuetify#1.0.11/dist/vuetify.js"></script>
<div id="app">
<v-app>
<v-content>
<v-container>
<v-text-field
color="cyan darken"
label="Text field"
multi-line
rows="2"
placeholder="Start typing..."
ref="messageBox"
#keydown.native="resizeTextarea"
:style="{height: height}"
id="textarea-element"
></v-text-field>
<p>
Scroll Height Using Refs Vuejs : <strong>{{ scrollHeightUsingDocumentObject}}</strong>
</p>
<p>
<span style="color:red">(Wrong)</span> Scroll Height Using Refs Vuejs : <strong>{{ scrollHeightUsingRefsVuejs }}</strong>
</p>
</v-container>
</v-content>
</v-app>
</div>
(To see the value of scrollHeight type anything if the textearea filed)
The this.$refs.messageBox.$el.scrollHeight refers to parent node input-group generated by Vuetify that’s way the value seems wrong , all we need just to add a selector to tearea node like this this.$refs.messageBox.$el.querySelector('textarea').scrollHeight