Vue vite (vuex,routing), change routing depending on dropdown search value? - javascript

Looking for tips to change routing details in a searchcomponent, depending on what value the user has in a selection dropdown.
Home.vue Components
<h4>Search for {{searchObj.whatSearch}}</h4>
<input type="text" placeholder="Search..." v-model='searchObj.searchString'>
<select name="searchOption" id="searchOption" v-model='searchObj.whatSearch'>
<option :value="'songs'">Song</option>
<option :value="'artists'">Artist</option>
<option :value="'albums'">Album</option>
</select>
</div>
<button #click="getMusic(searchObj)">Searchk</button>
//this is where I import my Searchcomponent
<div v-if="ifSearched">
<search-result/>
</div>
<script>
import SearchResult from './SearchResult.vue'
export default {
data(){
return{
ifSearched: false,
searchObj:{
whatSearch: 'songs',
searchString: '',
},
}
},
components:{
SearchResult,
},
methods:{
async getMusic(searchObj){
this.ifSearched = true
return await
this.$store.dispatch('fetchYouTubeApi', searchObj)
},
},
computed:{
getYTMusic(){
return this.$store.state.musicResult.content
}
}
}
</script>
And now in my searchComponent, I want to try to depending on my:
<select name="searchOption" id="searchOption" v-model='searchObj.whatSearch'>
<option :value="'songs'">Song</option>
<option :value="'artists'">Artist</option>
<option :value="'albums'">Album</option>
</select>
Change the routerlink to different routes. So in my SearchResult component looks like this
<div>
<h3>SearchResult</h3>
<div id="searchLoop"
v-for="(result, videoId) in getYTMusic"
:key="videoId">
<router-link type="button" :to="`/musicdetails/${result.browseId}`">
<p>{{result.name}}</p>
</router-link>
</div>
</div>
<script>
export default {
computed:{
getYTMusic(){
return this.$store.state.musicResults.content
}
}
}
</script>
So if the user selected songs for example, I want to router link to
<router-link type="button" :to="`/SongDetails/${result.browseId}`">
//or /ArtistDetails
//or /AlbumDetails
And so on, is it possible to use a v-if somehow?

I created a simple solution on how you could use a property to switch between different destinations on the same <router-link> element. The HTML could look like this:
<div>
<select name="searchOption" id="searchOption" v-model="testProp">
<option v-for="link in routerLinks" :value="link.value" :key="link.value">{{link.label}}</option>
</select>
</div>
<div>
<router-link type="button" :to="`/${testProp}`">
<p>{{testProp}}</p>
</router-link>
</div>
The script part would need the following properties for this example:
export default {
data() {
return {
testProp: "",
routerLinks: [
{ label: "Songs", value: "songs" },
{ label: "Artists", value: "artists" },
{ label: "Albums", value: "albums" }
]
}
}
}
In this example the value in routerLinks is your part of the url, which you want to switch according to the selected option. The selected option will be stored in testProp, which is used in <router-link> as :to value, while label from routerLinks is used inside of <router-link>.

Related

How to call Vue Js methods in Form-wizard or step-validation of jquery?

I used direct link of vue js and i want to call onchange method when i select option from dropdown. It's working fine when i put select tag out of wizard-form / steps-validation. When i put in in the wizard form or step form vue methods are not calling. I can access vue data but not access vue methods.
<form method="POST" enctype="multipart/form-data" class="wizard-form steps-validation" id="form">
<div id="calculation">
<div class="col-md-6">
<div class="form-group">
<label>Demo: <span class="text-danger">*</span></label>
<select name="country" data-placeholder="Select country" class="form-control form-control-select2" data-fouc v-model="country" v-select="country" #change="onChange($event)">
<option value="1">India</option>
<option value="2">USA</option>
</select>
</div>
</div>
</div>
</form>
<script>
Vue.directive('select', {
twoWay: true,
bind: function (el, binding, vnode) {
$(el).select2().on("select2:select", (e) => {
el.dispatchEvent(new Event('change', { target: e.target }));
});
},
});
var app = new Vue({
el: '#calculation',
data: {
country: ''
},
mounted: function () {
this.onChange();
},
methods: {
onChange(event) {
console.log('called change method');
}
}
});
</script>
If i understood your question correctly, the solution for you is .native event modifier

vue-multiselect not displaying array ( options: Array [0] )

I am attempting to add a vue-multiselect into an existing form, however, the dropdown is empty. This is more than a display issue as Vue devtools shows me my array is empty. I get no issues in the console.
The value for my select is from my API, I'm 99% sure my code there works, as it's exactly the same as I use elsewhere in my app to display a loop of the same values.
I'm using Nux.js.
Following the docs and other questions on SO, I feel I'm pretty close with the below code, but something must be amiss, I just can't spot it.
html
<template>
<section class="container">
<div>
<h1>Gins</h1>
<form #submit.stop.prevent="addGin">
<h2>New Gin</h2>
<p>
<label for="gin_name" class="input-label">Title:</label>
<input id="gin_name" v-model="gin_name" type="gin_name" name="gin_name" class="input">
</p>
<p>
<label for="description" class="input-label">Description:</label>
<input id="description" v-model="description" type="description" name="description" class="input">
</p>
<div>
<label for="distillery" class="input-label">Distillery:</label>
<multiselect
v-model="distillery_id"
track_by="id"
:options="options"
:searchable="true"
placeholder="Choose One Distillery"
>
</multiselect>
</div>
<p>
<input type="submit" value="Submit" class="button">
</p>
</form>
</div>
</section>
</template>
javascript
<script>
import axios from 'axios'
import Multiselect from 'vue-multiselect'
export default {
components: { Multiselect },
data() {
return {
gin_name: '',
description: '',
distillery_id: '',
options: []
}
},
methods: {
addGin() {
axios.post('http://localhost:4000/api/v1/gins', {
gin_name: this.gin_name, description: this.description
})
.then((response) => {})
},
getDistilleries() {
axios.get('/api/v1/distilleries')
.then((res) => {
this.options = res.data
})
.catch((error) => {
console.log(error)
})
}
}
}
</script>

How can i fetch value in JSON file by tag and city options with vue?

Firstly my english is not good. Sorry about that.
1-) My case is: when I write the necessary info into the gaps,- for example job name for one gap and for the other gap the city name(like istanbul)- I want to see the jobs in that city on page.
2-) Also, when i use the box to search for something, i need to use capital letters in order to see result. I want to see the result no matter how i type the letter, capital or not, How can i achieve this?
Thanks for all help.
this is full code
var app = new Vue({
el: "#app",
data: {
founded: [],
search: "",
show: false,
city: ""
},
created() {
fetch("job.json")
.then(res => {
return res.json();
})
.then(res => {
this.founded = res.items;
});
},
computed: {
filteredFounded: function() {
return this.founded.filter(items => {
return (
items.cityName === this.city && items.positionName.match(this.search)
);
});
}
}
});
<div class="header">
<h4>Get Job</h4>
</div>
<div id="app" class="nested">
<div class="card w-50">
<div class="search">
<input type="text" class="job" v-model="search" placeholder="Job..." #keypress.enter="founded">
<select name="" class="city" id="" v-model="city">
<option value="Seçiniz">Seçiniz</option>
<option value="İstanbul">İstanbul</option>
<option value="Ankara">Ankara</option>
<option value="İzmir">İzmir</option>
<option value="Çanakkale">Çanakkale</option>
</select>
</div>
<div class="find">
<button #click="show = true">Find!</button>
</div>
<div class="card-body" v-show="show" v-for="items in filteredFounded">
<h5 class="card-title">{{items.companyName}}</h5>
<p class="card-text">{{items.positionName}}</p>
<p class="card-text">{{items.cityName}}</p>
<p class="card-text">{{items.townName}}</p>
<p class="card-text">{{items.distance}}</p>
Go!
</div>
</div>
</div>
and this is job.json file
You can achieve this by first turning the required data into lower or uppercase letters. You do this using the toLowerCase() or toUpperCase() functions and then compare the data. For example, you can do something like this.
computed: {
filteredFounded: function () {
return this.founded.filter(items => {
return (
items.cityName.toLowerCase() === this.city.toLowerCase() && items.positionName.toLowerCase().match(this.search.toLowerCase())
);
});
}
}

passing data between components in vuejs

I've got my expense tracker app. I've got problem with adding Expense.
I've got two components responsible for this: addCategory.vue and selectCategory.vue.
This is my selectCategory.vue component:
<template>
<div>
<select class="custom-select" #selected="this.$emit('select-cat',category)">
<option v-for="category in categories">{{ category.title }}</option>
</select>
</div>
</template>
<script>
import axios from 'axios';
export default {
data() {
return {
categories: [],
errors: []
}
},
created() {
axios.get(`http://localhost:3000/categories`)
.then(response => {
this.categories = response.data;
console.log(response.data);
})
.catch(e => {
this.errors.push(e)
})
}
}
</script>
and this is my addExpense.vue component:
<template>
<div class="card">
<div class="card-header">
<h4>Dodaj nowy wydatek</h4>
</div>
<form v-on:submit.prevent="addExpense">
<div class="card-body">
<div class="form-group">
<label for="expense-name">Nazwa wydatku</label>
<input type="text" class="form-control" id="expense-name" v-model="Expense.title">
</div>
<div class="form-group">
<label for="expense-amount">Wartość</label>
<input type="number" class="form-control" id="expense-amount" v-model="Expense.amount">
</div>
<div class="form-group">
<label for="expense-date">Data wydatku</label>
<input type="date" class="form-control" id="expense-date" v-model="Expense.date">
</div>
<div class="form-group">
<label for="expense-category">Kategoria</label>
<select-category #select-cat="chooseCategory" v-model="Category.id"></select-category>
</div>
<br>
<div class="form-group">
<button class="btn btn-primary" #click="showAlert">Dodaj nowy wydatek</button>
</div>
</div>
</form>
</div>
</div>
</template>
<script>
import axios from 'axios';
import selectCategory from './selectCategory.vue';
export default {
components: {
'select-category': selectCategory
},
data(){
return {
Expense: {
title:'',
amount: '',
date:'',
categoryId:''
},
}
},
methods : {
chooseCategory(){
this.Expense.categoryId = this.Category.id
},
showAlert(){
this.$alert.success({
message: 'Wydatek dodany poprawnie'
})
},
addExpense(){
let newExpense = {
title : this.Expense.title,
amount : this.Expense.amount,
date : this.Expense.date,
categoryId: this.Expense.categoryId
}
console.log(newExpense);
axios.post(`http://localhost:3000/expenses`, newExpense)
.then((response) => {
console.log(response);
})
.catch((error) => {
console.log(error);
})
}
}
}
</script>
I need help because when I try to add the Expense, field with 'categoryId' remains empty.
I use Events to pass the name of categories but I dont know how to add category.id to Expense.
The issues in your codes:
you need to add one data property to save which option the user selected, so add one data property=selectedCategory
you didn't bind the value for the options of the select, and you didn't bind the value of the select, so add v-model="selectedCategory" for <select> and add :value="category" for <option>
It seems you bind wrong event (event=selected more likely is the event name you customized) for <select>, change to #change="selectChange(selectedCategory)"
Finally, in addExpense.vue, listen event=select-cat.
Like below demo:
Vue.config.productionTip = false
Vue.component('select-category', {
template: `<div>
<select class="custom-select" v-model="selectedCategory" #change="selectChange(selectedCategory)">
<option v-for="category in categories" :value="category">{{ category.title }}</option>
</select>
</div>`,
data() {
return {
categories: [],
errors: [],
selectedCategory: null
}
},
mounted() {
this.categories = [
{'id':1, 'title': 'abc'},
{'id':2, 'title': 'xyz'}
]
},
methods: {
selectChange: function(newCatetory) {
this.$emit('select-cat',newCatetory)
}
}
})
new Vue({
el: '#app',
data() {
return {
categorySelected: null
}
},
watch: {
categorySelected: function (newVal, oldVal) {
console.log('changed to ' + newVal.id + ' from ' + (oldVal ? oldVal.id : oldVal))
}
},
methods:{
chooseCategory: function(data) {
this.categorySelected = data
}
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.16/vue.js"></script>
<div id="app">
<div class="form-group">
<label for="expense-category">Kategoria</label>
<select-category #select-cat="chooseCategory($event)"></select-category>
</div>
</div>

Data not propagated from parent to child component

Vue suggests to use property-down and event-up pattern to propagate the data between parent and child components. Based on this I created a simple select-box component which lists all USA states and which emits 'state-selected' event. I'm subscribing to this event in my parent class and everything is ok.
Here is my code:
<template>
<select v-model="selectedStatus" id="orderStatusSelectBox" class="form-control" name="status" v-on:change="onChange" v-bind:preselectedStatus="filters.selectedStatus">
<option value="" selected="selected" disabled>Select status</option>
<option value="1">New</option>
<option value="2">Scheduling</option>
<option value="3">In production</option>
<option value="4">Completed</option>
<option value="5">On hold</option>
<option value="6">Cancelled</option>
<option value="7">Problem</option>
</select>
</template>
<script>
export default {
data: function () {
return {
selectedStatus: ''
}
},
mounted() {
this.selectedStatus = (this.preselectedStatus ? this.preselectedStatus : '');
},
component: 'select-order-status',
methods: {
onChange() {
this.$emit('statusSelected', this.selectedStatus);
}
},
props: ['preselectedStatus'],
}
</script>
In my parent component apart from this select box child component I have several buttons (quick filters) where you can quickly filter New orders or Completed orders. I added on-click events on those buttons so I can select new status and propagate that value to my child component.
Here is the code:
<template>
<div>
<div class="row filters">
<div class="col-md-12">
<h4>QUICK FILTERS:</h4>
</div>
</div>
<div class="row filters">
<div class="col-md-4">
<div class="row">
<div class="col-md-3">
<button type="button" class="btn btn-yellow m5 fixed-width-btn" v-on:click="statusSelected('1')">New Order</button>
<button type="button" class="btn btn-success m5 fixed-width-btn" v-on:click="statusSelected('4')">Completed</button>
</div>
</div>
</div>
</div>
<hr>
<div class="row">
<div class="col-md-2">
<div class="form-group">
<order-status-select v-on:statusSelected="statusSelected" v-bind:selectedStatus="filters.selectedStatus"></order-status-select>
</div>
</div>
</div>
<hr>
<span>
<div class="col-md-3">
<div class="form-group">
<select id="agentSelectBox" class="form-control" name="actions">
<option value="" selected="selected">Select action</option>
<option value="1">Action 1</option>
</select>
</div>
</div>
<div class="col-md-2">
<button type="button" class="btn btn-default">Apply</button>
</div>
<div class="col-md-2">
<button type="button" class="btn btn-default">Export CSV</button>
</div>
</div>
</div>
</template>
<script>
import OrderStatusSelectComponent from '../../reusable/OrderStatusSelectComponent.vue';
export default {
data: function () {
return {
filters: {
selectedStatus: '',
resultsPerPage: 10,
currentPage: 1,
},
}
},
mounted() {
},
component: 'filters',
methods: {
search() {
this.$emit('search', this.filters);
},
statusSelected(selectedStatus) {
this.filters.selectedStatus = selectedStatus;
}
},
components: {
'order-status-select': OrderStatusSelectComponent,
},
}
</script>
The problem is, when I click on any button (quick filter) that data is not propageted to child component.
I saw several other posts suggesting Vuex and Vue Bus but is there any other recommended way to handle this problem?
Here is peace of code that is making problems.
<order-status-select v-on:statusSelected="statusSelected" v-bind:selectedStatus="filters.selectedStatus"></order-status-select>
So from my parent component I want to pass filters.selectedStatus to the child component. When application renders first time status in filters.selectedStatus is correctly selected in my child component, but when ever I change filters.selectedStatus variable after, that will not reflect in child component.
Your child component is only checking the preselectedStatus on mount, and after the component has finished mounting it never looks at that property again, even if its value changes.
One way to deal with this is to have the child component watch its properties for changes, and respond as needed:
...
watch: {
preselectedStatus() {
// property value changed:
this.selectedStatus = (this.preselectedStatus ? this.preselectedStatus : '');
}
},
...

Categories

Resources