vue js vue-slider-component how to update props - javascript

I'm new to vue js and missing passing components prop.
Trying to make the vue-slider-component example to be vertical.
<vue-slider direction=vertical ></vue-slider>
and
<vue-slider :direction=vertical ></vue-slider>
failed, how should I pass props to component in the example?
Edit:
Tried what was suggested in comments:
<vue-slider direction={vertical} ></vue-slider>
and
<vue-slider :direction={vertical} ></vue-slider>

You should pass the value as string like this:
<vue-slider :direction="'vertical'"></vue-slider>
See the sample here
new Vue( {
el: '#app',
data () {
return {
}
},
methods: {
},
mounted () {
},
components: {
'vueSlider': window[ 'vue-slider-component' ],
}
})
#app {
margin: 50px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.4.2/vue.min.js"></script>
<script src="https://nightcatsama.github.io/vue-slider-component/dist/index.js"></script>
<div id="app">
<vue-slider :direction="'vertical'" :height="100" :width="6"></vue-slider>
</div>

The answer you're after is the magical
#app {
transform: rotate(90deg);
}
i'm not sure if this can be done via props... i'm honestly not all that familiar with vue-js so sorry to jump the gun on the answer. =)
to be more concise. Add a custom class to your slider and apply the rotate accordingly (so that you're not rotating you entire app =)

Related

Vue component not being rendered with props [duplicate]

This question already has an answer here:
Vue basics -- use component in other component
(1 answer)
Closed 2 years ago.
I am beginner in Vue. I created a custom component and tried to bind everything exactly as shown in the starter Vue cli template. Here is the code.
Circle.vue
<template>
<div :style="custom">
</div>
</template>
<script>
export default {
name:'Circle',
props:{
size:String,
color:String
},
computed:{
custom(){
return {
background:this.color,
height:this.size,
width:this.size
}
}
}
}
</script>
inside my View.vue file
<script>
// :class="['']"
import Circle from '#/components/Circle.vue'
export default {
name: "Landing",
components:{
Circle
}
};
</script>
I tried to use it so
<Circle size="100px" color="#222222"/>
I tried printing the props as it is but it also doesnt work
<template>
<div :style="custom">
{{size}} {{color}}
</div>
</template>
Nothing is being shown on the screen after I do this. I took help from here
Thanks for your time!
As mentioned in the docs:
Component names should always be multi-word, except for root App components, and built-in components provided by Vue, such as <transition> or <component>.
This prevents conflicts with existing and future HTML elements, since all HTML elements are a single word.
You have two options when defining component names:
With kebab-case
Vue.component('my-circle', { /* ... */ })
When defining a component with kebab-case, you must also use kebab-case when referencing its custom element, such as in <my-circle>.
With PascalCase
Vue.component('MyCircle', { /* ... */ })
When defining a component with PascalCase, you can use either case when referencing its custom element. That means both <my-circle> and <MyCircle> are acceptable.
Demo:
Vue.component('my-circle', {
props: {
size: String,
color: String
},
template: '<div :style="custom"></div>',
computed: {
custom() {
return {
background: this.color,
height: this.size,
width: this.size
}
}
}
})
new Vue({
el: "#myApp"
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.min.js"></script>
<div id="myApp">
<my-circle size="100px" color="#222222" />
</div>

Register Vue.js component dynamically from a string

I have a CRUD that enables me to write Vue.js component's code in the textarea like:
<template>
<div><p class='name-wrapper'>{{ model.name }}</p></div>
</template>
<script>
module.exports = {
name: 'NameWrapper',
props: ['model']
}
</script>
<style lang='sass'>
.name-wrapper
color: red
</style>
Then in other component, I fetch this data and want to register it as a dynamic/async, custom component like:
<template>
<component :is='dynamicName' :model='{name: "Alex"}'></component>
</template>
<script>
import httpVueLoader from 'http-vue-loader'
import Vue from 'vue'
export default {
name: 'DynamicComponent',
props: ['dynamicName', 'componentDefinitionFromTextareaAsString'],
beforeCreate: {
// I know that as a second parameter it should be an url to the file, but I can't provide it, but I would like to pass the contents of the file instead there:
httpVueLoader.register(Vue, this.$options.propsData.componentDefinitionFromTextareaAsString)
// I was trying also:
Vue.component(this.$options.propsData.dynamicName, this.$options.propsData.componentDefinitionFromTextareaAsString)
}
}
</script>
As far as I know, httpVueLoader needs the url to the .vue file instead - is there a way to pass there the code itself of the component?
I am aware that passing and evaluating <script></script> tag contents can cause security issues, but I really need to do it that way.
I've read also about Vue.js compile function, but that works only for templates, not the code of the component (so the script tags again).
Is it even possible to achieve such functionality in Vue.js?
It should be possible to use a data: URI with http-vue-loader, like this:
const vueText = `
<template>
<div class="hello">Hello {{who}}</div>
</template>
<script>
module.exports = {
data: function() {
return {
who: 'world'
}
}
}
<\/script>
<style>
.hello {
background-color: #ffe;
}
</style>
`
const MyComponent = httpVueLoader('data:text/plain,' + encodeURIComponent(vueText))
new Vue({
el: '#app',
components: {
MyComponent
}
})
<script src="https://unpkg.com/vue#2.6.10/dist/vue.js"></script>
<script src="https://unpkg.com/http-vue-loader#1.4.1/src/httpVueLoader.js"></script>
<div id="app">
<my-component></my-component>
</div>
If that doesn't work for some reason (maybe because one of your target browsers doesn't support it) then you could get it working by patching httpRequest. See https://www.npmjs.com/package/http-vue-loader#httpvueloaderhttprequest-url-. The documentation focuses on patching httpRequest to use axios but you could patch it to just resolve the promise to the relevant text.

VueJS get Width of Div

I have a Vue Component, that uses the bootstrap grid. In the child component I would like to get the current width of a certain div in the controller.
heres the child component:
<template>
<div id="bg-prev" ref="prev">
<h1>{{x}}</h1>
</div>
<template>
export default {
props: ['section'],
data() {
return {
x: 0,
y: 0,
}
},
mounted() {
this.getWindowWidth();
},
methods: {
getWindowWidth() {
this.x = this.$refs.prev.clientWidth;
}
}
};
<style>
#bg-prev {
width: 100%;
}
</style>
In this example the width will always be 0, even though the element has a clear width when I inspect it. What am I missing here, the mounted hook is the latest one in the vue lifecycle right? Any Help is appreciated ;)
Apart from a few typos the code is perfectly working. (missing closing template tag)
There is no additional hook needed. Only exception would be if you toggle the rendering of the Component in it's mounted method. Then you would use something like
const that = this
that.showDiv = true
that.$nextTick(function () {
that.getWindowWidth()
})
Are you sure it's parent is having a width during mounted? 100% of 0px is still 0px.

Vue v-model changes parent data but doesn't change value prop in custom component

someone to help me with this strange issue?
I have the following vue component:
<template lang="pug">
div
p.alert.alert-info {{value}}
button(#click="onChange") Change
</template>
<script>
import Vue from 'vue';
export default {
name: 'z-temp',
props: {
value: {
required: true
}
},
watch: {
value(val) {
console.log(val);
}
},
methods: {
onChange() {
this.$emit('input', Random.id());
}
}
};
</script>
I want to use v-model, but when I use <z-temp v-model="myDataField">, the myDataField changes with success when I click in the Change button, but when I make the inverse and put some value in myDataField, like myDataField: "foo" the custom component gets this.value as undefined instead as foo.
Can anyone help me please?
I am guessing that myDataField is not reactive so the problem is in the parent.
Can you clarify the problem, seems like it is working as it should, ie. the component does not seem to be the problem.
zTemp = Vue.component('ztemp', {
template: '#ztemp',
props: {
value: {
required: true
}
},
watch: {
value(val) {
console.log(val);
}
},
methods: {
onChange() {
this.$emit('input', Math.random());
}
}
});
new Vue({
el: '#app',
components: {
zTemp
},
data: {
myinput: '0.2'
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.4.4/vue.min.js"></script>
<div id="app">
{{myinput}}<br/>
<input v-model="myinput"/><br/>
<ztemp v-model="myinput"/><br/>
</div>
<script type="text/x-template" id="ztemp">
<div>
<p>{{value}}</p>
<button #click="onChange">Change</button>
</div>
</script>
thanks for helping, but I'm using meteor with vue-meteor, the problem was related to vue-meteor.
I changed the project structure to use separated Vue project in a .client folder and the problem gones. It was not a problema with component, but with vue-meteor package. Anyway, thank you guys.

Call a Vue.js component method from outside the component

Let's say I have a main Vue instance that has child components. Is there a way of calling a method belonging to one of these components from outside the Vue instance entirely?
Here is an example:
var vm = new Vue({
el: '#app',
components: {
'my-component': {
template: '#my-template',
data: function() {
return {
count: 1,
};
},
methods: {
increaseCount: function() {
this.count++;
}
}
},
}
});
$('#external-button').click(function()
{
vm['my-component'].increaseCount(); // This doesn't work
});
<script src="http://vuejs.org/js/vue.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="app">
<my-component></my-component>
<br>
<button id="external-button">External Button</button>
</div>
<template id="my-template">
<div style="border: 1px solid; padding: 5px;">
<p>A counter: {{ count }}</p>
<button #click="increaseCount">Internal Button</button>
</div>
</template>
So when I click the internal button, the increaseCount() method is bound to its click event so it gets called. There is no way to bind the event to the external button, whose click event I am listening for with jQuery, so I'll need some other way to call increaseCount.
EDIT
It seems this works:
vm.$children[0].increaseCount();
However, this is not a good solution because I am referencing the component by its index in the children array, and with many components this is unlikely to stay constant and the code is less readable.
In the end I opted for using Vue's ref directive. This allows a component to be referenced from the parent for direct access.
E.g.
Have a component registered on my parent instance:
var vm = new Vue({
el: '#app',
components: { 'my-component': myComponent }
});
Render the component in template/html with a reference:
<my-component ref="foo"></my-component>
Now, elsewhere I can access the component externally
<script>
vm.$refs.foo.doSomething(); //assuming my component has a doSomething() method
</script>
See this fiddle for an example: https://jsfiddle.net/0zefx8o6/
(old example using Vue 1: https://jsfiddle.net/6v7y6msr/)
Edit for Vue3 - Composition API
The child-component has to return the function in setup you want to use in the parent-component otherwise the function is not available to the parent.
Note: <sript setup> doc is not affacted, because it provides all the functions and variables to the template by default.
You can set ref for child components then in parent can call via $refs:
Add ref to child component:
<my-component ref="childref"></my-component>
Add click event to parent:
<button id="external-button" #click="$refs.childref.increaseCount()">External Button</button>
var vm = new Vue({
el: '#app',
components: {
'my-component': {
template: '#my-template',
data: function() {
return {
count: 1,
};
},
methods: {
increaseCount: function() {
this.count++;
}
}
},
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<my-component ref="childref"></my-component>
<button id="external-button" #click="$refs.childref.increaseCount()">External Button</button>
</div>
<template id="my-template">
<div style="border: 1px solid; padding: 2px;" ref="childref">
<p>A counter: {{ count }}</p>
<button #click="increaseCount">Internal Button</button>
</div>
</template>
For Vue2 this applies:
var bus = new Vue()
// in component A's method
bus.$emit('id-selected', 1)
// in component B's created hook
bus.$on('id-selected', function (id) {
// ...
})
See here for the Vue docs.
And here is more detail on how to set up this event bus exactly.
If you'd like more info on when to use properties, events and/ or centralized state management see this article.
See below comment of Thomas regarding Vue 3.
You can use Vue event system
vm.$broadcast('event-name', args)
and
vm.$on('event-name', function())
Here is the fiddle:
http://jsfiddle.net/hfalucas/wc1gg5v4/59/
A slightly different (simpler) version of the accepted answer:
Have a component registered on the parent instance:
export default {
components: { 'my-component': myComponent }
}
Render the component in template/html with a reference:
<my-component ref="foo"></my-component>
Access the component method:
<script>
this.$refs.foo.doSomething();
</script>
Say you have a child_method() in the child component:
export default {
methods: {
child_method () {
console.log('I got clicked')
}
}
}
Now you want to execute the child_method from parent component:
<template>
<div>
<button #click="exec">Execute child component</button>
<child-cmp ref="child"></child_cmp> <!-- note the ref="child" here -->
</div>
</template>
export default {
methods: {
exec () { //accessing the child component instance through $refs
this.$refs.child.child_method() //execute the method belongs to the child component
}
}
}
If you want to execute a parent component method from child component:
this.$parent.name_of_method()
NOTE: It is not recommended to access the child and parent component like this.
Instead as best practice use Props & Events for parent-child communication.
If you want communication between components surely use vuex or event bus
Please read this very helpful article
This is a simple way to access a component's methods from other component
// This is external shared (reusable) component, so you can call its methods from other components
export default {
name: 'SharedBase',
methods: {
fetchLocalData: function(module, page){
// .....fetches some data
return { jsonData }
}
}
}
// This is your component where you can call SharedBased component's method(s)
import SharedBase from '[your path to component]';
var sections = [];
export default {
name: 'History',
created: function(){
this.sections = SharedBase.methods['fetchLocalData']('intro', 'history');
}
}
Using Vue 3:
const app = createApp({})
// register an options object
app.component('my-component', {
/* ... */
})
....
// retrieve a registered component
const MyComponent = app.component('my-component')
MyComponent.methods.greet();
https://v3.vuejs.org/api/application-api.html#component
Here is a simple one
this.$children[indexOfComponent].childsMethodName();
I am not sure is it the right way but this one works for me.
First import the component which contains the method you want to call in your component
import myComponent from './MyComponent'
and then call any method of MyCompenent
myComponent.methods.doSomething()
Declare your function in a component like this:
export default {
mounted () {
this.$root.$on('component1', () => {
// do your logic here :D
});
}
};
and call it from any page like this:
this.$root.$emit("component1");
If you're using Vue 3 with <script setup> sugar, note that internal bindings of a component are closed (not visible from outside the component) and you must use defineExpose(see docs) to make them visible from outside. Something like this:
<script setup lang="ts">
const method1 = () => { ... };
const method2 = () => { ... };
defineExpose({
method1,
method2,
});
</script>
Since
Components using are closed by default
Sometimes you want to keep these things contained within your component. Depending on DOM state (the elements you're listening on must exist in DOM when your Vue component is instantiated), you can listen to events on elements outside of your component from within your Vue component. Let's say there is an element outside of your component, and when the user clicks it, you want your component to respond.
In html you have:
Launch the component
...
<my-component></my-component>
In your Vue component:
methods() {
doSomething() {
// do something
}
},
created() {
document.getElementById('outsideLink').addEventListener('click', evt =>
{
this.doSomething();
});
}
I have used a very simple solution. I have included a HTML element, that calls the method, in my Vue Component that I select, using Vanilla JS, and I trigger click!
In the Vue Component, I have included something like the following:
<span data-id="btnReload" #click="fetchTaskList()"><i class="fa fa-refresh"></i></span>
That I use using Vanilla JS:
const btnReload = document.querySelector('[data-id="btnReload"]');
btnReload.click();

Categories