Vue component is not inserted when called in HTML code - vue.js

I try to use Vue components, but it is not working.
I also use Pug(Jade) like preprocessor.
But in result HTML code I have raw template without transformation from Vue component to HTML code.
Here is Vue component:
Vue.component('date-input', {
props: ['id', 'format', 'value'],
mounted: function() {
$(this.$el).children().last().datepicker({
autoclose: true,
format: this.format || 'dd.mm.yyyy',
language: 'ru'
});
},
beforeDestroy: function() {
$(this.$el).children().last().datepicker('destroy');
},
methods: {
onInput: function(event) {
this.$emit('input', event.target.value);
},
onIconClick: function() {
$(this.$el).children().last().datepicker('show');
}
},
template: '<div class="date-field">' +
'<span class="icon calendar" #click="onIconClick"></span>' +
'<input id="id" class="form-control" type="text" #input="onInput" :value="value">' +
'</div>'
});
Here is PUG code:
+agreementModal('MYMODAL','MODAL NAME')
.date-range.text-nowrap
date-input.mr-3
date-input
Result HTML code:
<div class="date-range text-nowrap">
<date-input class="mr-3"></date-input>
<date-input></date-input>
</div>

Welcome to SO!
You do not seem to initialize your Vue app (with new Vue()) at some point.
Declaring Vue.component is important so that Vue knows what to do with your custom components, but you still need to tell Vue to start managing a part of your DOM by initializing it.
Vue.component('date-input', {
props: ['id', 'format', 'value'],
mounted: function() {
$(this.$el).children().last().datepicker({
autoclose: true,
format: this.format || 'dd.mm.yyyy',
language: 'ru'
});
},
beforeDestroy: function() {
$(this.$el).children().last().datepicker('destroy');
},
methods: {
onInput: function(event) {
this.$emit('input', event.target.value);
},
onIconClick: function() {
$(this.$el).children().last().datepicker('show');
}
},
template: '<div class="date-field">' +
'<span class="icon calendar" #click="onIconClick"></span>' +
'<input id="id" class="form-control" type="text" #input="onInput" :value="value">' +
'</div>'
});
new Vue({
el: '#app'
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<link rel="stylesheet" href="https://code.jquery.com/ui/1.12.0/themes/smoothness/jquery-ui.css" />
<script src="https://code.jquery.com/ui/1.12.0/jquery-ui.js"></script>
<script src="https://unpkg.com/vue#2"></script>
<div id="app" class="date-range text-nowrap">
<date-input class="mr-3"></date-input>
<date-input></date-input>
</div>

Related

Why v-text is not working to show a String

I tried to show particular string using v-text. But it shows nothing.
Tried code
ccc.handlebars
<div id="app">
<div class="input-group mb-3">
<input type="text" class="form-control" v-text="getValues[0].value">
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
var app = new Vue({
el: '#app',
data: {
'bulk': {{{bulks}}}
},
computed: {
getValues: function() {
return this.bulk;
}
},
methods: {},
});
</script>
getValues retuens JSON
[
{ name: "Dauth", age: "18", value: "TGFR123" }
]
I want to show TGFR123 in the text box
Above getValues returns the correct JSON. But v-text="getValues[0].value" not shows the string. Help me to solve this.
v-text does not work on input.
If you want to set the value of an input use :value or v-model
var app = new Vue({
el: '#app',
data: {
bulk: [{
name: "Dauth",
age: "18",
value: "TGFR123"
}]
},
computed: {
getValues: function() {
return this.bulk;
}
},
})
<script src="https://cdn.jsdelivr.net/npm/vue#2.6.0"></script>
<div id="app">
Bind : <input type="text" :value="getValues[0].value">
v-model : <input type="text" v-model="getValues[0].value">
<div>Result : {{getValues[0].value}}</div>
</div>
With v-model the data will be changed with the user input
v-text
value binding
You can use v-model or v-bind:value to insert this value in your input
var app = new Vue({
el: '#app',
data: {
bulk: [{id: 123, name: "Test", value: "NerF21_346"}]
},
computed: {
getValues() {
return this.bulk[0].value
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<input type="text" v-model="getValues">
</div>
v-model documentation

How to passing data from Vue instance into a Vue.component?

I have a Vue instance with two components. If the user clicks on a button in the second component I want to hide the template of first ones.
I have this code:
<div id="app">
<mycomp-one :active="active"></mycomp-one>
<mycomp-two></mycomp-two>
</div>
<template id="mycomponent-one">
<div v-show="!active">
<!-- ... --->
</div>
</template>
<template id="mycomponent-two">
<button v-on:click="setActive">Click Me</button>
</template>
With this script code:
Vue.component('mycomp-one', {
template: '#mycompnent-one',
// etc...
});
Vue.component('mycomp-two', {
template: '#mycomponent-two',
data: function() {
return {
active: false
};
},
methods: {
setActive: function() {
this.$parent.$options.methods.setActive();
},
},
});
new Vue({
el:'#app',
data:{
active: false
},
methods: {
setActive: function() {
this.active = !this.active;
},
},
});
If the button is clicked it working good to pass the information from the component to the instance. But here is stopping the data flow, the mycomp-one component did not get the change. How can I fix that? I want to hide the mycomp-one if the active is true.
this.$parent.$options.methods.setActive() is not a method bound to the Vue. I'm not sure how you got here, but this is not how you call a method on the parent.
console.clear()
Vue.component('mycomp-one', {
props:["active"],
template: '#mycomponent-one',
});
Vue.component('mycomp-two', {
template: '#mycomponent-two',
data: function() {
return {
active: false
};
},
methods: {
setActive: function() {
this.$parent.setActive();
},
},
});
new Vue({
el:'#app',
data:{
active: false
},
methods: {
setActive: function() {
this.active = !this.active;
},
},
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.3.4/vue.js"></script>
<div id="app">
<mycomp-one :active="active"></mycomp-one>
<mycomp-two></mycomp-two>
</div>
<template id="mycomponent-one">
<div v-show="!active">
Stuff
</div>
</template>
<template id="mycomponent-two">
<button v-on:click="setActive">Click Me</button>
</template>
Beyond that, components shouldn't call methods on their parent. They should emit events the parent listens to. This is covered well in the documentation.
console.clear()
Vue.component('mycomp-one', {
props:["active"],
template: '#mycomponent-one',
});
Vue.component('mycomp-two', {
template: '#mycomponent-two',
data: function() {
return {
active: false
};
},
methods: {
setActive: function() {
this.active = !this.active
this.$emit("set-active", this.active)
},
},
});
new Vue({
el:'#app',
data:{
active: false
},
methods: {
setActive: function() {
this.active = !this.active;
},
},
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.3.4/vue.js"></script>
<div id="app">
<mycomp-one :active="active"></mycomp-one>
<mycomp-two #set-active="active = $event"></mycomp-two>
</div>
<template id="mycomponent-one">
<div v-show="!active">
Stuff
</div>
</template>
<template id="mycomponent-two">
<button v-on:click="setActive">Click Me</button>
</template>

vuejs2 and chosen select issue

Good day, pls have a look at this bin. It was written Vue 0.12 version and chosen js. How can i make it work with vue2 version. i really need this as a directive not as a component.
`<div id='search`-results'>
Vue model value <br>
{{city | json}}
<hr>
Select value:
<!-- note the `v-model` and argument for `v-chosen` -->
<select class="cs-select" v-model="city" options="cities" v-chosen="city"></select>
<select v-model="city" options="cities"></select>
Vue.directive('chosen', {
twoWay: true, // note the two-way binding
bind: function () {
$(this.el)
.chosen({
inherit_select_classes: true,
width: '30%',
disable_search_threshold: 999
})
.change(function(ev) {
this.set(this.el.value);
}.bind(this));
},
update: function(nv, ov) {
// note that we have to notify chosen about update
$(this.el).trigger("chosen:updated");
}
});
var vm = new Vue({
data: {
city: 'Toronto',
cities: [{text: 'Toronto', value: 'Toronto'},
{text: 'Orleans', value: 'Orleans'}]
}
}).$mount("#search-results");
Here it is implemented as a wrapper component that supports v-model and a slot for the options. This makes it a drop-in replacement for a standard select widget, at least as far as basic functionality. The updated(), happily, will notice changes to the options list as well as to the value.
Since two-way directives are not supported in Vue2, I do not believe there is a way to implement this as a directive. If you really need that, you will want to use Vue1.
var vm = new Vue({
el: '#search-results',
data: {
city: 'Toronto',
cities: [{
text: 'Toronto',
value: 'Toronto'
}, {
text: 'Orleans',
value: 'Orleans'
}]
},
components: {
'chosenSelect': {
template: '<select class="cs-select" v-model="proxyValue" ><slot></slot></select>',
props: ['value', 'options'],
computed: {
proxyValue: {
get() {
return this.value;
},
set(newValue) {
this.$emit('input', newValue);
}
}
},
mounted() {
$(this.$el)
.chosen({
inherit_select_classes: true,
width: '30%',
disable_search_threshold: 999
})
.change((ev) => {
this.proxyValue = ev.target.value;
});
},
updated() {
$(this.$el).trigger('chosen:updated');
}
}
}
});
setTimeout(() => { vm.cities.push({text: 'Houston', value: 'Worth it'}); }, 1000);
<script src="//ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/chosen/1.4.2/chosen.proto.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/chosen/1.4.2/chosen.jquery.min.js"></script>
<link href="//cdnjs.cloudflare.com/ajax/libs/chosen/1.4.2/chosen.css" rel="stylesheet" />
<script src="//cdnjs.cloudflare.com/ajax/libs/vue/2.3.3/vue.min.js"></script>
<div id='search-results'>
Vue model value
<br> {{city | json}}
<hr> Select value:
<chosen-select v-model="city">
<option v-for="item in cities" :value="item.value">{{item.text}}</option>
</chosen-select>
<select v-model="city">
<option v-for="item in cities" :value="item.value">{{item.text}}</option>
</select>
</div>

Focus input of freshly added item

So I have a list of items and list of inputs linked to each item via v-for and v-model.
I click a button and add new item to that list. I want to focus input which is linked to newly added item.
Can't figure out how to achieve this goal.
<div id="app">
<div v-for="item in sortedItems">
<input v-model="item">
</div>
<button #click="addItem">
add
</button>
</div>
new Vue({
el: '#app',
data: {
items: []
},
methods: {
addItem: function() {
this.items.push(Math.random());
}
},
computed: {
sortedItems: function() {
return this.items.sort(function(i1, i2) {
return i1 - i2;
})
}
}
})
Here's fiddle with sorted list
https://jsfiddle.net/sfL91r95/1/
Thanks
Update: inspired by pkawiak's comment, a directive-based solution. I found that calling focus in the bind section didn't work; I had to use nextTick to delay it.
Vue.directive('focus-on-create', {
// Note: using Vue 1. In Vue 2, el would be a parameter
bind: function() {
Vue.nextTick(() => {
this.el.focus();
})
}
})
new Vue({
el: '#app',
data: {
items: []
},
methods: {
addItem: function() {
this.items.push(Math.random());
}
},
computed: {
sortedItems: function() {
return this.items.sort(function(i1, i2) {
return i1 - i2;
})
}
}
})
<script src="//cdnjs.cloudflare.com/ajax/libs/vue/1.0.26/vue.min.js"></script>
<div id="app">
<div v-for="item in sortedItems">
<input v-focus-on-create v-model="item">
</div>
<button #click="addItem">
add
</button>
</div>
Original answer:
Make your input a component so that you can give it a ready hook.
const autofocus = Vue.extend({
template: '<input v-model="item" />',
props: ['item'],
ready: function() {
this.$el.focus();
}
})
new Vue({
el: '#app',
data: {
items: []
},
methods: {
addItem: function() {
this.items.push(Math.random());
}
},
components: {
autofocus
},
computed: {
sortedItems: function() {
return this.items.sort(function(i1, i2) {
return i1 - i2;
})
}
}
})
<script src="//cdnjs.cloudflare.com/ajax/libs/vue/1.0.26/vue.min.js"></script>
<div id="app">
<div v-for="item in sortedItems">
<autofocus :item="item"></autofocus>
</div>
<button #click="addItem">
add
</button>
</div>
I Like to extend #Roy's answer.
if you are using any UI framework then it will create DIV and within the DIV input tag will be created so this Snippet will handle that case.
Vue.directive('focus-on-create', {
bind: function(el) {
Vue.nextTick(() => {
el.querySelector('input').focus()
})
}
})

Vue.js directive within a template

Based on this example https://vuejs.org/examples/select2.html
I try to create component for reuse in a future.
Unfortunately, my code doesn't work.
HTML:
<template id="my-template">
<p>Selected: {{selected}}</p>
<select v-select="selected" :options="options">
<option value="0">default</option>
</select>
</template>
<div id="app">
<my-component></my-component>
</div>
Vue:
Vue.component('my-component', {
template: '#my-template'
})
Vue.directive('select', {
twoWay: true,
priority: 1000,
params: ['options'],
bind: function () {
var self = this
$(this.el)
.select2({
data: this.params.options
})
.on('change', function () {
self.set(this.value)
})
},
update: function (value) {
$(this.el).val(value).trigger('change')
},
unbind: function () {
$(this.el).off().select2('destroy')
}
})
var vm = new Vue({
el: '#app',
data: {
selected: 0,
options: [
{ id: 1, text: 'hello' },
{ id: 2, text: 'what' }
]
}
})
https://jsfiddle.net/xz62be63/
Thank you for any help!
your problem has nothing to do with the directive itself.
selected and options is defined in the data of your Vue main instance, not in the data of my-component - so it's not available in its template.
But you can pass it from the main instance to the component using props:
<div id="app">
<my-component :selected.sync="selected" :options="options"></my-component>
<!-- added the .sync modifier to transfer the value change back up to the main instance-->
</div>
and in the code:
Vue.component('my-component', {
template: '#my-template',
props: ['selected','options']
})
updated fiddle: https://jsfiddle.net/Linusborg/rj1kLLuc/