Vue.js - How to get "this" object in componenet? - javascript

console.log(this) in doSomthing method, it is displayed "null".
I thought of console.log(this.currentPage) is displayed "main" but "this" object is null.. :(
How to access "main" of currentPage?
<template>
<div class="tab_menu_wrap">
<ul class="tab_menu">
<li v-for="tab in tabMenus" v-bind:class="{ active: tab.isActive }" v-on:click="doSomthing">
{{ tab.text }}
</li>
</ul>
</div>
</template>
<script>
export default {
name: 'tab-menu',
props: {
},
data() {
return {
currentPage: "main",
isActive: true,
tabMenus: [
{
text: 'A',
isActive: true
},
{
text: 'B',
isActive: false
},
{
text: 'C',
isActive: false
}
],
doSomthing: function(e){
console.log(this)
}
};
},
method: {
},
computed: {
}
};
</script>

I think data() should only have the state of your component, no actions.
Try moving your doSomething to methods in your component, like:
<template>
<div class="tab_menu_wrap">
<ul class="tab_menu">
<li v-for="tab in tabMenus" v-bind:class="{ active: tab.isActive }" v-on:click="doSomething">
{{ tab.text }}
</li>
</ul>
</div>
</template>
<script>
export default {
name: 'tab-menu',
props: {
},
data() {
return {
currentPage: "main",
isActive: true,
tabMenus: [
{
text: 'A',
isActive: true
},
{
text: 'B',
isActive: false
},
{
text: 'C',
isActive: false
}
]
};
},
methods: {
doSomething: function(e){
console.log(this)
}
},
computed: {
}
};
</script>

Related

require method images not rendered vue js

**The require method images are not rendered with Vuejs. Even though I've add the vue-loader dependency, and the props are delivered correctly. The template is simple - just an array in App component, a Parent and a Child component.
Can anyone help ?
https://codesandbox.io/s/eloquent-grass-j1usw8?file=/src/components/v-carousel-item.vue**
// App
<template>
<v-carousel :carousel_data="sliderItems" />
</template>
<script>
import vCarousel from "./components/v-carousel.vue";
export default {
name: "App",
data() {
return {
sliderItems: [
{ id: 1, name: "img1", img: "1.jpg" },
{ id: 2, name: "img2", img: "2.jpg" },
{ id: 3, name: "img3", img: "3.jpg" },
],
};
},
components: {
vCarousel,
},
};
</script>
//Parent
<template>
<div class="v-carousel"></div>
<v-carousel-item
v-for="item in carousel_data"
:key="item.id"
:item_data="item"
/>
</template>
<script>
import vCarouselItem from "./v-carousel-item.vue";
export default {
components: {
vCarouselItem,
},
props: {
carousel_data: {
type: Array,
default: () => [],
},
},
};
</script>
// Child
<template>
<div class="v-carousel-item">
<img src="require('../assets/images' + item_data.img)" alt="" />
</div>
</template>
<script>
export default {
props: {
item_data: {
type: Object,
default: () => {},
},
},
};
</script>

Vue component to change text based on data value

This is the data I get and I what to be able to replace the data content with readable text:
From parent:
data: [
{ name: 'discounts_offers', type: 'EMAIL', consent: true },
{ name: 'newsletter', type: 'EMAIL', consent: true },
{ name: 'product_upgrade', type: 'EMAIL', consent: true },
{ name: 'sms_offer', type: 'SMS', consent: true },
{ name: 'post_offer', type: 'POST', consent: true }
]
This is my included component
<CommunicationPreference
v-for="(communication, index) in data"
:key="index"
:communication="communication"
/>
Then the communicationPreference.vue:
<template>
<section>
{{ communication.name }} //This should be Newsletters etc
</section>
</template>
<script>
export default {
props: {
communication: {
type: Object,
default: null,
},
},
data() {
return {}
},
computed: {},
}
</script>
Then what I would like to do is if {{ communication.name }} equals 'discounts_offers' to use the text "Discounts and offers" like the images attached. Any solutions for the best approach to this?
You can use computed property for scenario like this. Something like this.
App.vue
<template>
<CommunicationPreference
v-for="(communication, index) in preferences"
:key="index"
:type="communication.type"
:name="communication.name"
v-model:consent="preferences[index].consent"
/>
</template>
<script>
import CommunicationPreference from "./components/CommunicationPreference.vue";
export default {
name: "App",
components: {
CommunicationPreference,
},
data() {
return {
preferences: [
{ name: "discounts_offers", type: "EMAIL", consent: true },
{ name: "newsletter", type: "EMAIL", consent: true },
{ name: "product_upgrade", type: "EMAIL", consent: true },
{ name: "sms_offer", type: "SMS", consent: true },
{ name: "post_offer", type: "POST", consent: true },
],
};
},
};
</script>
and in CommunicationPreference.vue
<template>
<div>
<label
><input
type="checkbox"
name="preference"
:value="consent"
:checked="consent === true"
#change="$emit('update:consent', $event.target.checked)"
/>{{ label }}</label
>
</div>
</template>
<script>
export default {
name: "CommunicationPreference",
props: {
type: String,
name: String,
consent: Boolean,
},
computed: {
label() {
if (this.name === "newsletter") {
return "Newsletters";
}
if (this.name === "discounts_offers") {
return "Discount and offers";
}
if (this.name === "product_upgrade") {
return "Upgrade recommendations";
}
return this.name;
},
},
};
</script>
Something like that....not tested though.

How to v-for checked value

I'm trying to create a checkbox select only one.
<div id="app">
<div v-for="(question, index) in questions">
<input type="checkbox" value="question.value" v-model="additional_grouped" #change="uniqueCheck"> {{question.title}}
</div>
{{ result }}
</div>
My JS looks like the following:
new Vue({
el: '#app',
data() {
return {
additional: [],
additional_grouped: [],
questions: [
{
title: 'A',
value: 0
},
{
title: 'B',
value: 1
},
{
title: 'C',
value: 2
}
]
}
},
computed: {
result: function(){
return this.additional.concat(this.additional_grouped);
}
},
methods: {
uniqueCheck(e){
console.log(e)
this.additional_grouped = [];
if (e.target.checked) {
this.additional_grouped.push(e.target.value);
}
}
}
});
This is the old result.
I'm trying to get results like this.
I can do this by not the v-for method, but I want to do it this way. Because I have a lot of data, How can I checked value in v-for?
Here is my pen: enter link description here
You are missing the value binding (:value), here's your example fixed:
new Vue({
el: '#app',
data() {
return {
additional: [],
additional_grouped: [],
questions: [
{
title: 'A',
value: 0
},
{
title: 'B',
value: 1
},
{
title: 'C',
value: 2
}
]
}
},
computed: {
result: function(){
return this.additional.concat(this.additional_grouped);
}
},
methods: {
uniqueCheck(e){
this.additional_grouped = [];
if (e.target.checked) {
this.additional_grouped.push(e.target.value);
}
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<div v-for="(question, index) in questions">
<input type="checkbox" :value="question.value" v-model="additional_grouped" #change="uniqueCheck"> {{question.title}}
</div>
{{ result }}
</div>
Documentation
uses :value="question.value" instead of value="question.value"
new Vue({
el: '#app',
data() {
return {
additional: [],
additional_grouped: [],
questions: [
{
title: 'A',
value: 0
},
{
title: 'B',
value: 1
},
{
title: 'C',
value: 2
}
]
}
},
computed: {
result: function(){
return this.additional.concat(this.additional_grouped);
}
},
methods: {
uniqueCheck(e){
this.additional_grouped = [];
if (e.target.checked) {
this.additional_grouped.push(e.target.value);
}
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<div v-for="(question, index) in questions">
<input type="checkbox" :value="question.value" v-model="additional_grouped" #change="uniqueCheck"> {{question.title}}
</div>
{{ result }}
</div>
If you want to get an array of the values of checked boxes, you should just do this
<div id="app">
<div v-for="(question, index) in questions" :key="index">
<input type="checkbox" v-model="question.checked"> {{question.title}}
</div>
{{ result }}
</div>
and
new Vue({
el: '#app',
data() {
return {
questions: [
{
title: 'A',
value: 0
},
{
title: 'B',
value: 1
},
{
title: 'C',
value: 2
}
]
}
},
computed: {
result: function(){
return this.questions.filter(q => q.checked).map(q => q.value)
}
}
});

Breadcrumb router dynamic

I have a problem when trying to make breadcrumb with vuejs, when the routes do not have parameters, it works, but for those routes that need a parameter, I do not know how to have the parameter in breadcrumb
Routes
{
path: '/',
component: () => import('#/components/kit/index'),
name: 'Home',
meta: {
requiresAuth: false,
visibleAfterLogin: true,
breadcrumb: [
{ name: 'Home' }
]
}
},
{
path: '/',
component: () => import('#/pages/kit/Layout'),
children: [
{
path: 'otherouter/:name',
name: 'Other',
components: {
default: () => import('#/components/kit/Other1'),
sidebar: () => import('#/components/kit/Sidebar')
},
meta: {
requiresAuth: false,
visibleAfterLogin: true,
breadcrumb: [
{ name: 'Home', link: 'Home' },
{ name: 'Other' }
]
}
},
{
path: 'studybook/:book',
name: 'Kit',
components: {
default: () => import('#/components/kit/TypeTrails'),
sidebar: () => import('#/components/kit/Sidebar')
},
meta: {
requiresAuth: false,
visibleAfterLogin: true,
breadcrumb: [
{ name: 'Home', link: 'Home' },
{ name: 'Trilhas', link: 'Other' },
{ name: 'Caderno de estudo' }
]
}
}
]
}
Breadcrumb.vue
<template>
<ul class="breadcrumbs">
<li v-for="(item, index) in breadcrumbList" :key="item.name">
<icon name="breadcrumb" size="13px" v-if="index === 0" #click="to(item)" />
{{item.name}}
<strong v-else>{{item.name}}</strong>
</li>
</ul>
</template>
<script>
export default {
data(){
return{
breadcrumbList: []
}
},
mounted(){
this.breadcrumbList = this.$route.meta.breadcrumb
},
watch: {
'$route' (){
this.breadcrumbList = this.$route.meta.breadcrumb
}
},
methods: {
to(item){
if(item.link){
this.$router.push({name: item.link})
}
}
}
}
</script>
maybe too late but you can achieve this making the breadcrumb a function receiving the route object for example:
// router file
{
path: '/items/:id',
...,
meta: {
breadcrumb: (route) => ([
{
name: 'My Items Index view',
to: { name: 'ItemIndex' }
},
{
name: 'My Item Detail view',
to: {
name: 'ItemDetail',
params: { id: route.params.id }
}
}
])
}
}
// app-bar or similar file
export default {
name: 'AppBar',
computed: {
breadcrumb() {
return this.$route.meta.breadcrumb(this.$route)
}
}
}

How to add checkboxes and link to a model in Vuejs Treeview?

I want to add checkboxes to Vuejs Treeview. So I added a checkbox to the template as this code:
<script type="text/x-template" id="item-template">
<li>
<input type="checkbox" id="checkbox">
<span
:class="{bold: isFolder}"
#click="toggle"
#dblclick="changeType">
{{ model.name }}
<span v-if="isFolder">[{{ open ? '-' : '+' }}]</span>
</span>
<ul v-show="open" v-if="isFolder">
<item
class="item"
v-for="(model, index) in model.children"
:key="index"
:model="model">
</item>
</ul>
</li>
</script>
But I don't know how to link those checkboxes to a model like this example. Please help! Thank you very much!
I think the simplest way to do that is by using VueX.
The store has a common variable for all checkBoxes accessible from everywhere.
When you click on a checkbox, it update the store.
https://jsfiddle.net/u91mxc58/14/
const store = new Vuex.Store({
state: {
checkBoxes:[],
},
mutations: {
updateCheckBoxes(state, value) {
state.checkBoxes = value;
}
}
})
// demo data
var data = {
name: 'My Tree',
children: [
{ name: 'hello' },
{ name: 'wat' },
{
name: 'child folder',
children: [
{
name: 'child folder',
children: [
{ name: 'hello' },
{ name: 'wat' }
]
},
{ name: 'hello' },
{ name: 'wat' },
{
name: 'child folder',
children: [
{ name: 'hello' },
{ name: 'wat' }
]
}
]
}
]
}
// define the item component
Vue.component('item', {
template: '#item-template',
props: {
model: Object,
},
data: function () {
return {
open: false
}
},
computed: {
isFolder: function () {
return this.model.children &&
this.model.children.length
},
checkBoxes: {
// accesseur
get: function () {
return store.state.checkBoxes;
},
// mutateur
set: function (newValue) {
store.commit('updateCheckBoxes', newValue);
}
}
},
methods: {
toggle: function () {
if (this.isFolder) {
this.open = !this.open
}
},
changeType: function () {
if (!this.isFolder) {
Vue.set(this.model, 'children', [])
this.addChild()
this.open = true
}
},
addChild: function () {
this.model.children.push({
name: 'new stuff'
})
}
}
})
// boot up the demo
var demo = new Vue({
el: '#demo',
data: function() {
return {
treeData: data
};
},
computed: {
checkBoxes() {
return store.state.checkBoxes;
}
}
})
body {
font-family: Menlo, Consolas, monospace;
color: #444;
}
.item {
cursor: pointer;
}
.bold {
font-weight: bold;
}
ul {
padding-left: 1em;
line-height: 1.5em;
list-style-type: dot;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vuex/3.0.1/vuex.js"></script>
<script src="https://unpkg.com/vue#latest/dist/vue.js"></script>
<!-- item template -->
<script type="text/x-template" id="item-template">
<li>
<input v-model="checkBoxes" type="checkbox" :value="model.name" id="checkbox">
<span
:class="{bold: isFolder}"
#click="toggle"
#dblclick="changeType">
{{ model.name }}
<span v-if="isFolder">[{{ open ? '-' : '+' }}]</span>
</span>
<ul v-show="open" v-if="isFolder">
<item
class="item"
v-for="(model, index) in model.children"
:key="index"
:model="model">
</item>
<li class="add" #click="addChild">+</li>
</ul>
</li>
</script>
<p>(You can double click on an item to turn it into a folder.)</p>
<!-- the demo root element -->
<ul id="demo">
<div>{{ checkBoxes }}</div>
<item
class="item"
:model="treeData">
</item>
</ul>

Categories

Resources