Vue3 is cutting properties from custom Elements used in App - vue.js

i want to include an external library in my Vue3 app. But when i try to inlcude them in my app, but some properties the element uses get cutted by Vue. Maybe someone can explain me this behaviour and how to fix this.
The attribute i am pointing on is "secondary"
vite.config.ts:
...
plugins: [
vue({
template: {
compilerOptions: {
// treat all tags with a dash as custom elements
isCustomElement: (tag) => {
return tag.includes("-");
},
},
},
}),
],
...
index.html
<div class="container">
<atom-button secondary>Test</atom-button>
<my-vue-comp></my-vue-comp>
</div>
in my component:
<template>
<div ref="root">
<atom-button secondary>Test</atom-button>
</div>
</template>
output in DOM:
<div class="container">
<atom-button secondary="" role="button" tabindex="0" type="button" aria-disabled="false">Test</atom-button>
<my-vue-comp>
<div>
<atom-button role="button" tabindex="0" type="button" aria-disabled="false">Test</atom-button>
</div>
</my-vue-comp>
</div>

Related

using vuejs how do i get the value of content in a div and display inside of the model

I am using vuejs and I want to get the value of a div and display it inside of the model. Issue is i Cannot use the recommended refs because I in reality cant modify the html. Does anyone have a basic solution where I can leverage vuejs and push the content to the model where location is?
new Vue({
el: "#app",
data: {
location:''
},
methods: {
test:function(){
if (!this.$refs.myRef) {
console.log("This doesn't exist yet!");
}
}
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<div id="FilePathPlaceholder" class="d2l-placeholder d2l-placeholder-live" aria-live="assertive">
<div class="d2l_1_234_979">
<div class="d2l_1_235_849 d2l_1_236_43 d2l-inline">
<span class="d2l-textblock"></span>
<span
class="d2l-textblock d2l_1_237_505 d2l_1_238_137"
id="d2l_1_233_684"
title="/content/Stuff/12183-CC-242/">
/content/Stuff/
<strong>12183-CC-242</strong>/
</span>
<input type="hidden" name="FilePath" id="FilePath" value="/content/Stuff/12183-CC-242/">
</div>
<div class="d2l_1_237_505 d2l-inline">
<span class="d2l-validator" id="d2l_1_239_562"></span>
</div>
</div>
</div>
</div>

Conditional a href in Vuejs

I am rendering a list of store titles in VueJS, some of them have a url property, some of them don't. If the title has a url, I want to add a a href property:
<div v-for="(store, index) in stores">
<span v-if="store.link"><a :href="store.link" target="_blank">{{ store.title }}</a></span>
<span v-else="store.link">{{ store.title }}</span>
</div>
This works, but the code looks duplicated. Is there anyway to simplify the code further?
you can use component tag:
var app = new Vue({
el: '#app',
data () {
return {
stores: [
{title:'product1',link:'/products/222'},
{title:'product2'},
{title:'product3',link:'/products/333'},
{title:'product4'}
]
}
}
})
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<div id="app">
<div v-for="(store, index) in stores">
<component :is="store.link?'a':'span'" :href="store.link || ''" target="_blank">{{store.title}}
</component>
</div>
</div>
I'd remove the first span element, as it's not necessary. Also, the v-else does not need the conditional statement (it's not v-else-if):
new Vue({
el: '#app',
data: {
stores: [
{ link: 'foo', title: 'foo-text' },
{ title: 'bar-text' }
]
}
})
<script src="https://unpkg.com/vue"></script>
<div id="app">
<div v-for="(store, index) in stores" :key="index">
<a v-if="store.link" :href="store.link" target="_blank">{{ store.title }}</a>
<span v-else>{{ store.title }}</span>
</div>
</div>
You can use dynamic arguments in vue3
https://v3.vuejs.org/guide/template-syntax.html#dynamic-arguments
<a v-bind:[attributeName]="url"> ... </a>
or binding an object of attributes
<div v-bind="{ id: someProp, 'other-attr': otherProp }"></div>

How can I get value in datetimepicker bootstrap on vue component?

My view blade, you can see this below :
...
<div class="panel-body">
<order-view v-cloak>
<input slot="from-date" data-date-format="DD-MM-YYYY" title="DD-MM-YYYY" type="text" class="form-control" placeholder="Date" name="from_date" id="datetimepicker" required>
<input slot="to-date" data-date-format="DD-MM-YYYY" title="DD-MM-YYYY" type="text" class="form-control" placeholder="Date" name="to_date" id="datetimepicker" required>
</order-view>
</div>
...
My order-view component, you can see this below :
<template>
<div>
<div class="col-sm-2">
<div class="form-group">
<slot name="from-date" required v-model="fromDate"></slot>
</div>
</div>
<div class="col-sm-1">
<div class="form-group" style="text-align: center">
-
</div>
</div>
<div class="col-sm-2">
<div class="form-group">
<slot name="to-date" required v-model="toDate"></slot>
</div>
</div>
<div class="col-sm-4">
<button v-on:click="filter()" class="btn btn-default" type="button">
<span class="glyphicon glyphicon-search"></span>
</button>
</div>
</div>
</template>
<script>
export default {
data() {
return{
fromDate: '',
toDate: ''
}
},
methods: {
filter: function() {
console.log(this.fromDate)
console.log(this.toDate)
}
}
}
</script>
I using v-model like above code
But, when I click the button, the result of
console.log(this.fromDate)
console.log(this.toDate)
is empty
It display empty
Why it does not work?
How can I solve it?
You cannot bind a slot using v-model and expect that Vue will attach that automatically to your slot input, but I can't see any reason why you need to use a slot here anyway. It looks like you just want an input that you can attach custom attributes to and you can do that by passing the attributes as a prop and use v-bind to bind them:
<template>
<div>
<input v-bind="attrs" v-model="fromDate" />
<button #click="filter">filter</button>
</div>
</template>
export default{
props: ['attrs'],
methods: {
filter() {
console.log(this.fromDate)
}
},
data() {
return {
fromDate: ""
}
}
}
new Vue({
el: "#app",
data: {
fromDateAttrs: {
'data-date-format': "DD-MM-YYYY",
title: "DD-MM-YYYY",
type: "text",
class: "form-control",
placeholder: "Date",
name: "from_date",
id: "datetimepicker",
}
}
});
Now you can just pass your attrs as a prop in the parent:
<my-comp :attrs="fromDateAttrs"></my-comp>
Here's the JSFiddle: https://jsfiddle.net/rvederzc/
EDIT
In reference as to how to create a date picker component, here's how I would implement a jQuery datepicker using Vue.js:
<template id="date-picker">
<div>
<input v-bind="attrs" v-model="date" #input="$emit('input', $event.target.value)" v-date-picker/>
</div>
</template>
<script type="text/javascript">
export default {
props: ['attrs'],
directives: {
datePicker: {
bind(el, binding, vnode) {
$(el).datepicker({
onSelect: function(val) {
// directive talk for 'this.$emit'
vnode.context.$emit('input', val);
}
});
}
}
}
}
</script>
You can then bind that with v-model in the parent:
<date-picker v-model="myDate"></date-picker>
Here's the JSFiddle: https://jsfiddle.net/g64drpg6/
Cant expect any javascript technology to be complete before it becomes famous. Going by that, I tried all the recommendations from using moment to vue-datapicker. All recommendations heavily broke design and needed hardcode of the div id's in the vue initialisation under mounted. Cant introduce hacks into my project this way. Messes up design and implementation neatness.
I fixed it using plain old jsp. On Save, I just did this
vuedata.dateOfBirthMilliSecs = $("#dateOfBirth").val() ;
I'll figure out conversion of date format to milliseconds in my java controller.

How to perform a transition on a simply component load with Vue.js

This is what the Vue.js documentation state:
Vue provides a transition wrapper component, allowing you to add
entering/leaving transitions for any element or component in the
following contexts:
Conditional rendering (using v-if)
Conditional display (using
v-show)
Dynamic components
Component root nodes
I just simply have a component that is loaded and filled out with XHR data though. How do I go about using a transition to show when the elements v-for gets the data array from an ajax request and builds up my template?
I want a nice fade in instead of simply "plopping" the data into the dom. and have it show up with a delay out of nowhere.
My components example:
https://jsfiddle.net/uwk1x1bx/
<template>
<transition name="fade">
<div class="row">
<div class="col-md-12" v-for="faq in faqs">
<h2>{{ faq.description }}</h2>
<div v-for="item in faq.items" class="panel panel-default">
<div class="panel-heading">{{ item.description }}</div>
<div class="panel-body" v-html="item.answer"></div>
</div><!-- /.panel -->
</div><!-- /.col-md-12 -->
</div><!-- /.row -->
</transition>
</template>
JS
<script>
export default {
name: "Faq",
data() {
return {
faqs: []
}
},
created() {
this.fetchFaqData();
},
methods: {
fetchFaqData() {
Vue.http.get('/services/getfaq').then((response) => {
this.faqs = response.data;
}, (response) => {
console.log(response);
})
}
}
}
</script>

Vue JS Component reattach or Cache

VueJS component doesn't get cached or atleast reattached after navigation. On refresh or launch everything gets attached and rendered well but after navigating to another page then back. The First Component - Carousel - component in my case doesn't get rendered but the API call is made.
<template>
<div class="rel">
<div id="homeCarousel" class="owl-carousel owl-slider">
<div class="item" v-for="product in featured">
<div class="bg-holder top-area-half" >
<div class="bg-mask-lighten"></div>
<img class="bg-img" v-bind:src="product.feature_image_url">
<div class="hero-caption">
<div class="container">
<h3 class="hero-title">{{product.feature_title}}</h3>
<p class="hero-subtitle">{{product.feature_subtitle}}</p>
<a class="btn btn-white btn-ghost btn-lg hero-btn" href="#">Shop now</a>
</div>
</div>
</div>
</div>
</div>
<div id="hero-slider-nav" class="hero-slider-nav">
<div class="container">
<div class="pull-right"></div>
</div>
</div>
</div>
</template>
<style>
</style>
<script>
export default{
data(){
return{
featured:[]
}
},
ready(){
},
mounted(){
this.getFeaturedProducts();
},
components:{
},
methods: {
getFeaturedProducts: function () {
Vue.http.get('/api/product/filter/featured=1').then(
(response) => {
this.featured = response.body;
}
)
}
}
}
</script>
`
<template>
<div class="global-wrapper clearfix ">
<keep-alive>
<Carousel></Carousel>
</keep-alive>
//The rest of the code which is just importing the Component
I found out what i was doing wrong. I had a separate JS/JQuery file and on the document ready i was initializing an owl carousel by id #('homeCarousel').owlCarousel({}) . What worked was, since i had already bootstrapped owl carousel -> on the mounted lifecycle callback i was now targeting the element and making it an owl carousel.