Use Lang.js in a component property - vuejs2

I want to parse a Lang.js localized string as a property to a component.
<my-component :placeholder="placeholder"></my-component>
export default {
name: 'Test',
data: function() {
return {
placeholder: {{ 'messages.Placeholder' | trans }}, <!-- not working -->
}
},
methods: {
}
}
Unfortunately placeholder: {{ 'messages.Placeholder' | trans }} wont work

The solution was easier as expacted.
<my-component :placeholder="'messages.Placeholder' | trans"></my-component>

Related

Vuejs props with a long path

I have a component with props like that:
props: {
data: Object
},
data display: {{ data.a.b.c.d.title }}
I want to create a variable like: d = this.data.a.b.c.d.
data display: {{ d.title }}
What is the best practice to create this variable?
Use a computed prop, like this...
props: {
data: Object
},
computed: {
d() {
return this.data.a.b.c.d;
}
},
<!-- in the markup -->
<p>{{ d.title }}</p>

Select first option by default using v-model

Can someone help with this problem? I have a dynamic select dropdown. The first default option of "Choose your location" is not visible by default. This is because of v-model. How can I get that working?
My parent component:
<template>
<div>
<Segments #select-segment-location-event="updateSegmentLocation" :segmentLocation="segmentLocation" />
</div>
</template>
My child component:
<template>
<div class="container">
<select v-model="segmentLocation" #change="selectSegmentLocation">
<option selected disabled>Choose your location...</option>
<option v-for="(segLoc, index) in segmentLocations"
:key="index"
:value="segLoc">{{ segLoc.name }}</option>
</select>
</div>
</template>
<script>
export default {
data() {
return {
segmentLocations: [
{ value: "Residential", name: 'Residential building' },
{ value: "Workplace", name: 'Workplace' },
{ value: "Hospitality", name: 'Hospitality or Retail' },
{ value: "Real Estate", name: 'Real Estate' },
{ value: "Commercial Parking", name: 'Commercial Parking' },
{ value: "Fleets", name: 'Fleets' },
{ value: "Cities & Governments", name: 'Cities & Governments' },
{ value: "Corridor", name: 'Highway, Corridor or Petrol Station' }
],
}
}
methods: {
selectSegmentLocation() {
this.$emit('select-segment-location-event', this.segmentLocation);
}
}
};
</script>
From what I see, the segmentLocation variable is passed as a prop to the Segments component.
You should avoid mutating a prop with v-model in the child component, because each component should only mutate it's own state.
I propose a few changes, add a new selectedSegmentLocation variable in your data method, with a default value of "NOT_SELECTED" :
data() {
return {
selectedSegmentLocation: "NOT_SELECTED",
segmentLocations: []
}
}
Then, in your template, update the Choose your location... option to have a value attribute:
<option selected value="NOT_SELECTED" disabled>Choose your location...</option>
Now, update the v-model and the selectSegmentLocation method to use the new variable:
<select v-model="selectedSegmentLocation" #change="selectSegmentLocation">
selectSegmentLocation() {
this.$emit('select-segment-location-event', this.selectedSegmentLocation);
}
If you still want to use the passed prop segmentLocation as a default value, use it in the created() hook, but you should have 'NOT_SELECTED' as the default value if you want to show the 'Choose your location' option.
created() {
this.selectedSegmentLocation = this.segmentLocation ? this.segmentLocation : "NOT_SELECTED";
}
And, if you want to be able to change the selected value from the parent, you can watch the segmentLocation property:
watch: {
segmentLocation() {
if (this.segmentLocation) {
this.selectedSegmentLocation = this.segmentLocation;
}
}
}

Watch props from children component vue.js

I have two components "number-iput" and "basket input". How i can watch props from number-input (value) in basket-input?
Number Input component:
<template lang="pug">
.field
.number-input
button.number-input__btn(#click.prevent="minus")
i.i.i-minus
input(type="number" v-model="value" #input="valuecheck")
button.number-input__btn(#click.prevent="plus")
i.i.i-plus
</template>
<script>
export default {
name: "number-input",
props: {
value: {
type: Number,
default: 1
},
min: {
type: Number,
default: 1
},
max: {
type: Number,
default: 999999999
},
current: {
type: Number,
default: 1
}
},
methods: {
plus() {
if(this.value < this.max) this.value++;
},
minus() {
if(this.value > this.min) this.value--;
},
valuecheck() {
if(this.value > this.max) this.value = this.max
}
},
watch: {
value: function() {
if(parseInt(this.value) > parseInt(this.max)) this.value = this.max
}
}
}
</script>
Basket-input
<template lang="pug">
.basket-item
a.basket-item__image(href="")
img(:src="image", :alt="title")
.basket-item__info
span.basket-item__caption {{ code }}
a.basket-item__title(href="") {{ title }}
span.basket-item__instock(v-if="instock && instock > 0") В наличии ({{ instock }} шт)
span.basket-item__instock(v-else) Нет в наличии
.basket-item__numbers
number-input(min="1" max="99" :value="numberofitems")
.basket-item__lastcol
.column-price(v-if="price")
b {{ numberofitems * price }} ₽
span(v-if="numberofitems > 1") {{ numberofitems }} × {{ price }} ₽
button.basket-item__remove Удалить товар
</template>
<script>
export default {
name: 'basketitem',
props: {
image: {
type: String,
required: true
},
title: {
type: String,
required: true
},
code: {
type: String,
required: true
},
instock: {
type: Number
},
price: {
type: Number
},
numberofitems: {
type: Number,
default: 1
}
},
}
</script>
In basket input i need to watch number-input(value) and write it in numberofitems prop..
Im trying all, but my knowledge of vue is too low for that (
Props are mechanism to pass data only in one way - that means you can pass a value from parent to child but child is not allowed to change the value. If you do, Vue will warn you.
Way around it to use events. The principle is wildly know as "props-down, events-up".
You pass value to Child via prop
When Child want to change the value, instead of changing it directly, it will emit the event with new value
Parent component needs to handle that event and change its internal value (change will propagate into child item via prop)
You can read about various ways to do it for example here
Computed properties can help with that:
<template>
<input type="number" v-model="internalValue" />
</template>
<script>
export default {
props: {
value: {
type: Number,
default: 1
}
},
computed: {
internalValue: {
get: function() {
return this.value
},
set: function(newValue) {
this.$emit('valueChanged', newValue)
}
}
}
}
</script>
And in your parent component:
<template>
<mycomponent :value="value" #valueChanged="value = $event"/>
<mycomponent :value="value" #valueChanged="onValueChanged"/>
</template>
<script>
export default {
data: {
value: 0
},
methods: {
onValueChanged(newValue) {
this.value = newValue;
}
}
}
</script>
Notes
with larger and more complicated applications it can be better to use some solutions with shared global state like Vuex
Your Basket-input component has same problem because its receives numberofitems via prop

wrap template component with his name

I have components and I would like every component template wrapped inside a div with his name.
Vue.component('search', {
template: '<div>component template</div>'
html result
<div class="component-search">
<div>component template</div>
</div>
I can't imagine why you would want to be do that but anyhow you could do the following
Vue.component('search', {
name: 'search',
template: `<div :class="wrapperClass">
<div>component template</div>
</div>`,
computed: {
componentName() {
return this.$options.name
},
wrapperClass() {
return `component-${this.componentName}`
},
}
})

How to use filters in Vue js?

I need to use filter "capitalize" in vue js 2, but when I add filters according to documentation, it gave me error.
my code
<template>
<div class="test">
<h1>{{title}}</h1>
<ul>
<li v-for="item in items | capitalize" :key="item.first">{{item.first}},{{item.last}}</li>
</ul>
</div>
</template>
<script>
export default {
name: 'test',
vinput: '',
data () {
return {
title: 'Hello,
items: [
{
first: 'John0',
last: 'Doe'
},
{
first: 'Pavel',
last: 'Doe'
},
{
first: 'Shox',
last: 'Doe'
}
]
}
},
filters: {
capitalize: function (value) {
if (!value) return ''
value = value.toString()
return value.charAt(0).toUpperCase() + value.slice(1)
}
}
}
</script>
error
enter image description here
Any ideas, how to corrext that error?
Use filters in the template syntax.
<li v-for="item in items" :key="item.first">{{item.first | capitalize}},{{item.last | capitalize}}</li>
First, we have to define in main.js as shown below.
Vue.filter('UpperCase', function(val) {
return val.toUpperCase()
})
Then, we have to use where we need as shown below.
<div>{{ name | UpperCase }}</div>
Whatever function you want, just write function and call it.