How to use filters in Vue js? - 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.

Related

Vue Component Select option from list item

I'm new to Vue. I have an autocomplete component that used AXIOS to get the data. When I type in at least 3 characters, it does display the results in a list item, however I can't seem to figure out how to actually select the option and populate the text field.
Here is the code
<template>
<div>
<input type="text" placeholder="Source client" v-model="query" v-on:keyup="autoComplete" #keydown.esc="clearText" class="form-control">
<div class="panel-footer" v-if="results.length">
<ul class="list-group">
<li class="list-group-item" v-for="result in results">
<span> {{ result.name + "-" + result.oid }} </span>
</li>
</ul>
</div>
</div>
</template>
<script>
import axios from 'axios'
export default{
data(){
return {
selected: '',
query: '',
results: []
}
},
methods: {
clearText(){
this.query = ''
},
autoComplete(){
this.results = [];
if(this.query.length > 2){
axios.get('/getclientdata',{params: {query: this.query}}).then(response => {
this.results = response.data;
});
}
}
}
}
</script>
Any help would be appreciated!
Writing an autocomplete is a nice challenge.
You want this component to act like an input. That means that if you'd use your autocomplete component, you will probably want to use it in combination with v-model.
<my-autocomplete v-model="selectedModel"></my-autocomplete>
To let your component work in harmony with v-model you should do the following:
Your component should accept a prop named value, this may be a string, but this may also be an object.
In the example above the value of selectedModel will be available inside your autocomplete component under '{{value}}' (or this.value).
To update the value supplied you $emit an input event with the selected value as second parameter. (this.$emit('input', clickedItem))
Inside your autocomplete you have query, which holds the search term. This is a local variable and it should be. Don't link it to value directly because you only want to change the value when a user selects a valid result.
So to make the example work you could do the following:
<template component="my-autocomplete">
<div>
<input type="text" placeholder="Source client" v-model="query" v-on:keyup="autoComplete" #keydown.esc="clearText" class="form-control">
<div class="panel-footer" v-if="results.length">
<ul class="list-group">
<li class="list-group-item" v-for="result in results" #click="selectValue(result)">
<span> {{ result.name + "-" + result.oid }} </span>
</li>
</ul>
</div>
</div>
</template>
<script>
//import axios from 'axios'
export default{
props: ['value'],
data(){
return {
selected: '',
query: '',
results: []
}
},
methods: {
clearText(){
this.query = ''
},
autoComplete(){
this.results = [];
if(this.query.length > 2){
this.results = [{ name: 'item 1', oid: '1' }, {name: 'item 2', oid: '2'}];
//axios.get('/getclientdata',{params: {query: this.query}}).then(response => {
//this.results = response.data;
//});
}
},
selectValue(selectedValue) {
this.$emit('input', selectedValue);
}
}
}
</script>
I commented out the axios part for demonstration purposes.
To verify the workings:
<template>
<div>Autocomplete demo:
<my-autocomplete v-model="selectedRow">
</my-autocomplete>
Selected value: <pre>{{selectedRow}}</pre>
</div>
</template>
<script>
export default {
data() {
return {
selectedRow: null
}
}
}
</script>
Now the autocomplete does what it should, it allows you to search and pick a valid result from the list.
One problem remains though. How do you display the selected value. Some options are:
Copy the value to query, this works seemlessly if all your options are strings
Copy the value of result.name to query, this would make the solution work
Accept a scoped slot from the parent component which is responsible for displaying the selected item.
I will demonstrate option 2:
<template component="my-autocomplete">
<div>
<input type="text" placeholder="Source client" v-model="query" v-on:keyup="autoComplete" #keydown.esc="clearText" class="form-control">
<div class="panel-footer" v-if="results.length">
<ul class="list-group">
<li class="list-group-item" v-for="result in results" #click="selectValue(result)">
<span> {{ result.name + "-" + result.oid }} </span>
</li>
</ul>
</div>
</div>
</template>
<script>
//import axios from 'axios'
export default{
props: ['value'],
data(){
return {
selected: '',
query: '',
results: []
}
},
mounted() {
if (this.value && this.value.name) {
this.query = this.value.name;
}
},
// Because we respond to changes to value
// we do not have to do any more work in selectValue()
watch: {
value(value) {
if (this.value && this.value.name) {
this.query = this.value.name;
} else {
this.query = '';
}
}
},
methods: {
clearText(){
this.query = ''
},
autoComplete(){
this.results = [];
if(this.query.length > 2){
this.results = [{ name: 'item 1', oid: '1' }, {name: 'item 2', oid: '2'}];
//axios.get('/getclientdata',{params: {query: this.query}}).then(response => {
//this.results = response.data;
//});
}
},
selectValue(selectedValue) {
this.$emit('input', selectedValue);
}
}
}
</script>
A working example can be found here: https://jsfiddle.net/jangnoe/4xeuzvhs/1/

Vue.js - Inject el elements to html

I have website for online tests.
One of the question that i have created on the test its topic "Fill in the blank", which means fill in the blank spaces words.
The question comes from the server as a string like that "Today is a [1] day, and i should [2] today".
What i want to do is to get that string and replace all the [] with el-input.
I have done something like that
<template>
<div class="d-flex flex-column mg-t-20 pd-10">
<h6 class="tx-gray-800">Fill in the blank areas the missing words</h6>
<div class="mg-t-20" v-html="generateFillBlankQuestion(question.question)" />
</div>
</template>
<script>
export default {
name: 'FillBlank',
directives: {},
props: [ 'question' ],
components: {
},
computed: {},
data() {
return {
input: ''
}
},
filters: {},
created() {
},
methods: {
generateFillBlankQuestion(question) {
var matches = question.match((/\[\d\]/g))
console.log(matches)
matches.forEach((element) => {
console.log(element)
question = question.replace(element, '<el-input />')
})
console.log(question)
return question
}
}
}
On this line question = question.replace(element, '<el-input />') I'm replacing the [] to input.
For some reason when i try to replace it to <el-input> it doesn't render it.
But if i use <input type='text'> it renders it.
Is it possible to inject el elements?
If you are not using the Vue run-time template compiler you can not render Vue components inside v-html. You should do something like this:
<template>
<div class="d-flex flex-column mg-t-20 pd-10">
<h6 class="tx-gray-800">Fill in the blank areas the missing words</h6>
<div class="mg-t-20">
<template v-for="(word,idx) in wordList">
<el-input v-if="word.blank" v-model="word.value" :key="idx" />
<template v-else>{{ word.text }}</template>
</template>
</div>
</div>
</template>
<script>
export default
{
name: 'FillBlank',
props:
{
question:
{
type: String,
default: ''
}
},
computed:
{
wordList()
{
const words = this.question.split(' ');
return words.map(word =>
({
value: '',
text: word,
blank: /^\[\d+\]$/.test(word),
}));
}
}
}

Assign function to multiple elements in one statement in VueJs

I have multiple inputs and single function for #keyup event:
<template>
<div class="box">
<input v-model="metaData.description" #keyup="changeElement(id)"/>
<input v-model="metaData.sortOrder" #keyup="changeElement(id)"/>
<input v-model="metaData.cols" #keyup="changeElement(id)"/>
</div>
</template>
export default {
name: "ModelAuto",
props: ["id", "nodes", "type"],
data: function() {
return {
metaData: {
description: "",
cols: 2,
sortOrder: 0
}
};
},
methods: {
changeElement: function(id) {
this.$root.$emit("changeElementEvent", id, this.metaData);
}
}
Is it possible to assign function changeElement to all inputs in one place (in one line of code instead of adding #keyup="changeElement(id)" to each input in template)? Something like
$('input').keyup(changeElement(id))

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 can I add operator ternary in input type text on vue.js 2?

My vue component like this :
<template>
<div>
...
<li v-for="category in categories">
...
<input type="radio" class="category-radio" :value="category.id" (category.id == categoryId) ? 'checked data-waschecked=true' : ''>
...
</li>
...
</div>
</template>
<script>
export default {
props: ['categories', 'categoryId'],
}
</script>
I want to add condition in input type text. I use operator ternary like above code
If the code executed, it does not work
There is no error. So i'm confused to solve it
Maybe my code is still not correct
How can I solve it?
The issue is you're trying to use JavaScript expression inside plain HTML. This won't work.
You can either bind each attribute manually like this:
:checked="(expression) ? true : false"
or bind to a computed property which depends on your expression and returns your calculated property. Alternatively, you can bind an object with one to many properties, and bind the whole object at once (this is possible also):
new Vue({
el: '#app',
data: {
categories: [
{ id: 1, name: 'one' },
{ id: 2, name: 'two' },
{ id: 3, name: 'three' }
],
selectedId: 2 // for simplicity
},
computed: {
attrs: function() {
return function(id) { // computed can also return a function, so you can use args
return (id === this.selectedId) ? { checked: true, 'data-waschecked': true } : {}
}
}
},
mounted() { // log your element
console.log(document.querySelector('input[data-waschecked=true]'))
}
});
<script src="https://unpkg.com/vue/dist/vue.js"></script>
<div id="app">
<ul>
<li v-for="category in categories">
<input type="checkbox" v-bind="attrs(category.id)">
</li>
</ul>
</div>