How to make the fields independent? - vue.js

I'm trying to make the fields/buttons independent of one another. Just like in the case of Adding more people. Example image
No matter how many fields I add, they'll not be linked to each other. I can remove/edit one of them and it'll only affect that field.
but I'm not sure how can I achieve similar behavior If I need to repeat same fields. If I click on Add Other City, a new city block would be created but with the previous data. Example image.
HTML:
<div id="app">
<div v-model="cities" class="city">
<form action="" v-for="(city, index) in cities">
<div class="column" v-for="(profile, index) in profiles">
<input type='text' v-model="profile.name" placeholder="Name">
<input type='text' v-model="profile.address" placeholder="Address">
<button type="button" #click="removeProfile">-</button>
</div>
<center><button type="button" #click="addProfile">Add More People</button></center>
<br><br><br>
</form>
<center>
<button type="button" #click="addCity">Add Other City</button>
<button type="button" #click="removeCity">Remove City</button>
</center>
</div>
</div>
JS:
new Vue({
el: '#app',
data: {
cities: [
{ name: '' }
],
profiles: [
{ name: '', address: '' }
],
},
methods: {
addProfile() {
this.profiles.push({
name: '',
address: ''
})
},
removeProfile(index) {
this.profiles.splice(index, 1);
},
addCity() {
this.cities.push({
// WHAT TO DO HERE?
})
},
removeCity(index) {
this.cities.splice(index, 1);
},
}
})
Here's a link to Jsfiddle: https://jsfiddle.net/91m8cf5q/4/
I first tried to do this.profiles.push({'name': '', 'address': ''}) inside this.cities.push({}) in addCity() but It's not possible (gives error).
What should I do to make them separate so that when I click Add Other City, new blank field would appear and removing fields from that city should not remove fields from the previous cities.

You should have profiles assigned to individual city
new Vue({
el: '#app',
data: {
cities: [],
},
mounted(){
this.cities.push({
name: '',
profiles: [
{
name: '',
address: '' }
]
});
},
methods: {
addProfile(index) {
this.cities[index].profiles.push({
name: '',
address: ''
})
},
removeProfile(index) {
this.profiles.splice(index, 1);
},
addCity() {
this.cities.push({
name: '',
profiles: [
{
name: '',
address: '' }
]
})
},
removeCity(index) {
this.cities.splice(index, 1);
},
}
})
#app form {
margin: 5px;
width: 260px;
border: 1px solid green;
padding-top: 20px;
}
.column {
padding: 5px;
}
.city {
width: 280px;
border: 1px solid red;
margin: 10px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<div class="city">
<form action="" v-for="(city, index) in cities">
<div class="column" v-for="(profile, index) in city.profiles">
<input type='text' v-model="profile.name" placeholder="Name">
<input type='text' v-model="profile.address" placeholder="Address">
<button type="button" #click="removeProfile">-</button>
</div>
<center><button type="button" #click="addProfile(index)">Add More People</button></center>
<br><br><br>
</form>
<center>
<button type="button" #click="addCity">Add Other City</button>
<button type="button" #click="removeCity">Remove City</button>
</center>
</div>
</div>

Profiles should be part of cities, like this
new Vue({
el: '#app',
data: {
cities: [{
name: '',
profiles: [
{ name: '', address: '' }
]}
]
},
methods: {
addProfile(city) {
city.profiles.push({
name: '',
address: ''
})
},
addCity() {
this.cities.push(
{ name: '',
profiles: [
{ name: '', address: '' }
]}
)
},
removeCity(index) {
this.cities.splice(index, 1);
},
}
})
HTML:
<div id="app">
<div class="city">
<form v-for="city in cities">
<div class="column" v-for="profile in city.profiles">
<input type='text' v-model="profile.name" placeholder="Name">
<input type='text' v-model="profile.address" placeholder="Address">
<button type="button" #click="removeProfile">-</button>
</div>
<center>
<button type="button" #click="addProfile(city)">Add More People</button>
</center>
<br><br><br>
</form>
<center>
<button type="button" #click="addCity">Add Other City</button>
<button type="button" #click="removeCity">Remove City</button>
</center>
</div>
<div>

Related

How to remove html tags

Hi everyone I want to not show "html tags" When i have data in tables, but i want show text only like microsoft word, I'm not sure on the support, I don't know to fix it and I have tried many times, I think can't to remove all the html tags from string, I used CKeditor to input and datatable of vue output from vueX
help me please
Example Outpout
<template>
<div class="container" id="annoucements">
<div class="row">
<div class="col-md-12">
<div class="card">
<div class="card-header card-header-primary card-header-icon">
<div class="card-icon">
<i class="material-icons">assignment</i>
</div>
<h4 class="card-title">
{{ $t('global.table') }}
<strong>{{ $t('cruds.annoucement.title') }}</strong>
</h4>
</div>
<div class="card-body">
<div class="row">
<div class="col-md-12">
<div class="table-overlay" v-show="loading">
<div class="table-overlay-container">
<material-spinner></material-spinner>
<span>Loading...</span>
</div>
</div>
<datatable
:columns="columns"
:data="data"
:total="total"
:query="query"
:xprops="xprops"
:HeaderSettings="false"
:pageSizeOptions="[10, 25, 50, 100]"
>
<global-search :query="query" class="pull-left" />
<span style="margin-left:10%">
<button
type="button"
class="btn btn-default"
#click="fetchIndexData"
:disabled="loading"
:class="{ disabled: loading }"
>
<i class="material-icons" :class="{ 'fa-spin': loading }">
refresh
</i>
{{ $t('global.refresh') }}
</button>
</span>
<header-settings :columns="columns" class="pull-right" />
</datatable>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
import { mapGetters, mapActions } from 'vuex'
import TranslatedHeader from '#components/Datatables/TranslatedHeader'
import HeaderSettings from '#components/Datatables/HeaderSettings'
import GlobalSearch from '#components/Datatables/GlobalSearch'
import DatatableAttachments from '#components/Datatables/DatatableAttachments'
export default {
components: {
GlobalSearch,
HeaderSettings
},
data() {
return {
columns: [
{
title: 'cruds.annoucement.fields.id',
field: 'id',
thComp: TranslatedHeader,
sortable: true,
colStyle: 'width: 100px;'
},
{
title: 'cruds.annoucement.fields.annoucement',
field: 'annoucement',
thComp: TranslatedHeader,
tdComp: DatatableAttachments
},
{
title: 'cruds.annoucement.fields.name',
field: 'name',
thComp: TranslatedHeader,
sortable: true
},
{
title: 'cruds.annoucement.fields.number',
field: 'number',
thComp: TranslatedHeader,
sortable: true
},
{
title: 'cruds.annoucement.fields.short_name',
field: 'short_name',
thComp: TranslatedHeader,
sortable: true
},
{
title: 'cruds.annoucement.fields.allow_date',
field: 'allow_date',
thComp: TranslatedHeader,
sortable: true
},
{
title: 'cruds.annoucement.fields.description',
field: 'description',
thComp: TranslatedHeader,
}
],
query: { sort: 'id', order: 'desc', limit: 100, s: '' },
xprops: {
module: 'AnnoucementsIndex',
route: 'annoucements',
permission_prefix: 'annoucement_'
}
}
},
beforeDestroy() {
this.resetState()
},
computed: {
...mapGetters('AnnoucementsIndex', ['data', 'total', 'loading'])
},
watch: {
query: {
handler(query) {
this.setQuery(query)
this.fetchIndexData()
},
deep: true
}
},
methods: {
...mapActions('AnnoucementsIndex', [
'fetchIndexData',
'setQuery',
'resetState'
])
}
}
</script>
Use method below for each cell or make an copy of data that contains string without html:
removeHtmlTags(htmlString) {
const tmp = document.createElement('DIV');
tmp.innerHTML = htmlString;
return tmp.textContent || tmp.innerText || '';
}

Vue draggable works for whole group but not for each item

The code below allows dragging the groups in toListFetchRouteA1:
<draggable id="first" data-source="juju" :list="toListFetchRouteA1" class="list-group" draggable=".item" group="a">
<div class="list-group-item item" v-for="teamfetch in toListFetchRouteA1" :key="teamfetch.id">
<div v-for="personame in teamfetch.Team_player_sessions" :key="personame.id">
{{personame.Player.Person.first_name}}
</div>
</div>
</draggable>
I am trying to allow dragging each person name rather than by group, so I changed :list="toListFetchRouteA1" into :list="teamfetch.Team_player_sessions" (shown below), but it throws an error: Cannot read property 'Team_player_sessions' of undefined".
<draggable id="first" data-source="juju" :list="teamfetch.Team_player_sessions" class="list-group" draggable=".item" group="a">
<div v-for="teamfetch in toListFetchRouteA1" :key="teamfetch.id">
<div class="list-group-item item" v-for="personame in teamfetch.Team_player_sessions" :key="personame.id">
{{personame.Player.Person.first_name}}
</div>
</div>
</draggable>
It does not drag as well. Is there a way to make div v-for="personame in teamfetch.Team_player_sessions draggable for personname?
The error occurs because teamfetch is out of scope. It was declared on the inner v-for but used in the outer element.
You could make the person names draggable by wrapping them in a second draggable (assuming you want the groups themselves and the names within the groups to be draggable):
<draggable :list="toListFetchRouteA1" class="list-group" draggable=".item" group="a">
<div class="list-group-item item" v-for="teamfetch in toListFetchRouteA1" :key="teamfetch.id">
<!-- 2nd draggable for persons -->
<draggable :list="teamfetch.Team_player_sessions" draggable=".person">
<div v-for="personame in teamfetch.Team_player_sessions" :key="personame.id" class="person">
{{personame.Player.Person.first_name}}
</div>
</draggable>
</div>
</draggable>
new Vue({
el: '#app',
data: () => ({
toListFetchRouteA1: [
{
id: 1,
Team_player_sessions: [
{
id: 100,
Player: {
Person: {
first_name: 'john'
}
}
}
]
},
{
id: 2,
Team_player_sessions: [
{
id: 200,
Player: {
Person: {
first_name: 'adam'
}
}
},
{
id: 201,
Player: {
Person: {
first_name: 'allen'
}
}
}
]
},
{
id: 3,
Team_player_sessions: [
{
id: 300,
Player: {
Person: {
first_name: 'dave'
}
}
},
{
id: 301,
Player: {
Person: {
first_name: 'dylan'
}
}
}
]
},
]
}),
})
.item {
background: #eee;
margin: 2px;
padding: 10px;
}
.person {
background: #ccc;
margin: 2px;
}
<script src="https://unpkg.com/vue#2.6.11"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/vue/2.5.2/vue.min.js"></script>
<script src="//cdn.jsdelivr.net/npm/sortablejs#1.8.4/Sortable.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/Vue.Draggable/2.20.0/vuedraggable.umd.min.js"></script>
<div id="app">
<draggable :list="toListFetchRouteA1" class="list-group" draggable=".item" group="a">
<div class="list-group-item item" v-for="teamfetch in toListFetchRouteA1" :key="teamfetch.id">
<draggable :list="teamfetch.Team_player_sessions" draggable=".person">
<div v-for="personame in teamfetch.Team_player_sessions" :key="personame.id" class="person">
{{personame.Player.Person.first_name}}
</div>
</draggable>
</div>
</draggable>
<pre>{{toListFetchRouteA1}}</pre>
</div>

Custom radio component in latest Vue would not function at all in latest Safari

UPDATE: It is an issue of not being able to render the active class. Click does log data .
Expected
Current
RadioInput
<RadioInput
v-model="form.userType"
label="User Type"
:options="[
{ id: 'two', name: 'Investor', checked: true },
{ id: 'one', name: 'Entrepreneur', checked: false }
]"
/>
<template>
<ValidationProvider
class="mb-4 RadioInput"
tag="div"
data-toggle="buttons"
:rules="rules"
:name="name || label"
v-slot="{ errors, required, ariaInput, ariaMsg }"
>
<label
class="form-label"
:for="name || label"
#click="$refs.input.focus()"
:class="{ 'text-gray-700': !errors[0], 'text-red-600': errors[0] }"
>
<span>{{ label || name }} </span>
<small>{{ required ? " *" : "" }}</small>
</label>
<div class="btn-group btn-block btn-group-toggle" data-toggle="buttons">
<label
:for="item.id"
v-for="item in options"
class="btn btn-light"
:class="{ 'active': item.checked }"
>
<input
#click="update(item.name)"
type="radio"
:name="name || label"
class="form-control custom-control-input"
:id="item.id"
ref="input"
v-bind="ariaInput"
autocomplete="off"
:checked="item.checked"
/>
{{ item.name }}
</label>
</div>
<span
:class="{ 'invalid-feedback': errors[0] }"
v-bind="ariaMsg"
v-if="errors[0]"
>{{ errors[0] }}</span
>
</ValidationProvider>
</template>
<script>
import { ValidationProvider } from "vee-validate";
export default {
name: "RadioInput",
components: {
ValidationProvider
},
props: {
name: {
type: String,
default: ""
},
label: {
type: String,
default: ""
},
rules: {
type: [Object, String],
default: ""
},
options: {
type: Array,
default: []
}
},
methods: {
update(value) {
this.$emit("input", value);
}
},
created() {
this.$emit(
"input",
_.filter(this.options, { checked: true })[0]["name"]
);
}
};
</script>
<style scoped>
.invalid-feedback {
display: block;
}
</style>
const Wrapper = Vue.component("Wrapper", {
props: ["options", "activeIndex"],
template: `<div>
<div v-for="(item, index) in options" class="item" :class="{active: index === activeIndex}" #click="$emit('input', index)">{{item.name}}</div>
</div>`,
});
new Vue({
el: "#app",
template: `<div>
<Wrapper :options="options" :activeIndex="activeIndex" v-model="activeIndex"></Wrapper>
</div>`,
data() {
return {
options: [
{ id: "two", name: "Investor", checked: true },
{ id: "one", name: "Entrepreneur", checked: false }
],
activeIndex: -1
};
},
created() {
this.activeIndex = this.options.findIndex(i => i.checked);
}
});
body{
display: flex;
justify-content: center;
align-items: center;
}
.item{
width: 100px;
border: 1px solid;
padding: 10px;
}
.item.active{
background-color: rgba(0,0,0, 0.3);
}
<script src="https://cdn.jsdelivr.net/npm/vue#2.6.0"></script>
<div id="app"></div>

Vue components all acting as one

I have three components. All of them bind a value.
Below is the blade file with the three components
Blade File:
<div id="app">
<div class="row">
<div class="col-4">
<crud-component :type="'tower'"></crud-component>
</div>
<div class="col-4">
<crud-component :type="'country'"></crud-component>
</div>
<div class="col-4">
<crud-component :type="'department'"></crud-component>
</div>
</div>
</div>
All of these components are dynamic, they only rely on that binded value called :type
The Vue file:
<template>
<div>
<h3>{{capitalize(type)}} <button class="btn btn-primary btn-sm" #click="showAddModal()">Add</button></h3>
<datatable :columns="columns" :sortKey="sortKey" :sortOrders="sortOrders">
<tbody v-if="loading">
<tr>
<td colspan="11"><div class="lds-dual-ring mx-auto"></div></td>
</tr>
</tbody>
<tbody v-else>
<tr v-for="data in retData" :key="data.id">
<td> {{data.id}}</td>
<td> {{data.name}}</td>
<td>
<button class="btn btn-warning btn-sm" #click="showEditModal(data)"> Edit </button>
<button class="btn btn-danger btn-sm" #click="showDeleteModal(data)"> Delete </button>
</td>
</tr>
</tbody>
</datatable>
<!-- MODALS -->
<modal :name="type + '-add-modal'" height="auto">
<div class="row p-3">
<div class="col-12">
<h3>Add {{capitalize(type)}}</h3>
<hr>
<form>
<div class="form-group">
<label for="add-item">{{capitalize(type)}} Name</label>
<input v-validate="'required'" type="text" name="item-name" class="form-control" id="add-item-name" required>
<small class="form-text text-danger">{{errors.first('item-name')}}</small>
</div>
<button type="button" class="float-right btn btn-sm btn-primary" #click="store">Submit</button>
</form>
</div>
</div>
</modal>
<modal :name="type + '-edit-modal'" height="auto">
<div class="row p-3">
<div class="col-12">
<h3>Edit {{capitalize(type)}}</h3>
<hr>
<form>
<div class="form-group">
<label for="edit-item">{{capitalize(type)}} Name</label>
<input v-validate="'required'" name="item-name" type="text" class="form-control" id="edit-item-name" v-model="currentItem.name" required>
<small class="form-text text-danger">{{errors.first('item-name')}}</small>
</div>
<button type="button" class="float-right btn btn-sm btn-primary" #click="store">Submit</button>
</form>
</div>
</div>
</modal>
<modal :name="type + '-delete-modal'" height="auto">
<div class="row p-3">
<div class="col-12">
<h3>Delete {{capitalize(type)}}</h3>
<hr>
<p class="lead">Are you sure you want to delete <strong>{{currentItem.name}}</strong>?</p>
<button type="button" class="float-right btn btn-sm btn-primary" #click="destroy">Submit</button>
</div>
</div>
</modal>
</div>
</template>
<script>
import Datatable from './utilities/DatatableComponent.vue';
import Pagination from './utilities/PaginationComponent.vue';
export default {
components: {
'datatable': Datatable,
'pagination': Pagination,
},
props: ['type'],
mounted() {
this.get(this.type);
},
data() {
let sortOrders = {};
let columns = [
{label: 'ID', name:'id', isSortable: true},
{label: 'NAME', name:'name', isSortable: true},
{label: 'ACTIONS', name:'actions', isSortable: false}
];
columns.forEach(column => {
sortOrders[column.name] = -1;
});
return {
loading: true,
currentItem: '',
isUpdate: false,
sortKey: 'id',
columns: columns,
sortOrders: sortOrders,
tableData: {
draw: 0,
length: 10,
search: '',
column: 'id',
dir: 'desc',
},
pagination: {
lastPage: '',
currentPage: '',
total: '',
lastPageUrl: '',
prevPageUrl: '',
nextPageUrl: '',
from: '',
to: '',
},
retData: []
};
},
methods: {
showEditModal(item) {
this.currentItem = item;
this.$modal.show(this.type + '-edit-modal');
this.isUpdate = true;
},
showAddModal() {
this.$modal.show(this.type + '-add-modal');
},
store() {
this.$validator.validate().then(valid => {
if(!valid) {
return;
} else {
if(this.isUpdate == true) {
axios.post('/api/crud/store', {
type: this.type,
item: this.currentItem,
isUpdate: this.isUpdate
}).then(response => {
this.get(this.type);
this.$modal.hide(this.type + '-edit-modal');
this.isUpdate = false;
this.currentItem = '';
});
} else {
axios.post('/api/crud/store', {
type: this.type,
name: $('#add-item-name').val(),
isUpdate: this.isUpdate
}).then(response => {
this.get(this.type);
this.$modal.hide(this.type + '-add-modal');
});
}
}
});
},
showDeleteModal(item) {
this.currentItem = item;
this.$modal.show(this.type + '-delete-modal');
},
destroy() {
axios.delete('/api/crud/delete', {
data: {
type: this.type,
item: this.currentItem
}
}).then(response => {
this.$modal.hide(this.type + '-delete-modal')
this.currentItem = '';
this.get(this.type)
});
},
capitalize(s) {
if (typeof s !== 'string') return ''
return s.charAt(0).toUpperCase() + s.slice(1)
},
get(type) {
axios.interceptors.request.use(config => {
NProgress.start();
this.loading = true;
return config;
});
axios.interceptors.response.use(response => {
NProgress.done();
this.loading = false;
return response;
});
this.tableData.draw++;
axios.post('/api/crud', {
type: type,
tableData: this.tableData
}).then(response => {
let data = response.data;
if(this.tableData.draw == data.draw) {
this.retData = data.data.data
}
console.log('Done');
});
},
}
}
</script>
<style>
.lds-dual-ring {
display: block;
width: 64px;
height: 64px;
}
.lds-dual-ring:after {
content: " ";
display: block;
width: 46px;
height: 46px;
margin: 5px;
border-radius: 50%;
border: 5px solid #000;
border-color: #000 transparent #000 transparent;
animation: lds-dual-ring 1.2s linear infinite;
}
#keyframes lds-dual-ring {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
</style>
The problem is, when I'm trying to update, fetch, or do anything with one component.
It runs all of the API calls to fetch their specific data.
I just want to have that one table load when it's fetching data.
As mentioned in my comment above, you are adding interceptors to your Axios instance every time any of your components calls its get method.
The interceptor code runs on every request / response made through Axios, no matter where it comes from. This is why all your components appear to be loading when a request is made.
I suggest you remove the interceptors and change your code to
get(type) {
NProgress.start()
this.loading = true
this.tableData.draw++
axios.post('/api/crud', {
type: type,
tableData: this.tableData
}).then(response => {
NProgress.done()
this.loading = false
let data = response.data;
if(this.tableData.draw == data.draw) {
this.retData = data.data.data
}
})
}
Data needs to be a function.
data () {
return {
...
}
}
You can't simply have a bunch of variables and also a function like you have. You need to refactor your component.

Multi selected Filter in Vue.js

I have a selection of checkbox groups (hotel type and locations) and I want to filter the results based on what has been selected. How can I add my selectedLocations and types to the filteredHotels() method and get a filtered result. Sydney Hotels, Sydney Backpackers, Sydney or Melbourne hotels or all Hotels if only hotels is selected.
HTML
<div>
<div class="row pt-5">
<div class="col">
<h5>Locations</h5>
<label v-for="(value, key) in locations">
{{value}}
<input type="checkbox" :value="value" v-model="selectedLocations">
</label>
{{selectedLocations}}
</div>
</div>
<div class="row pt-5">
<div class="col">
<h5>Type</h5>
<label v-for="(value, key) in types">
{{value}}
<input type="checkbox" :value="value" v-model="selectedTypes">
</label>
{{selectedTypes}}
</div>
</div>
<transition-group class="row" style="margin-top:30px;" name="list" tag="div" mode="out-in">
<div class="col-sm-4 pb-3 list-item" v-for="(hotel, index) in filteredHotels" :key="index">
<div class="sau-card">
<i class="fal fa-server fa-3x"></i>
<h2>{{hotel.name}}</h2>
<p>{{hotel.type}}</p>
<p>{{hotel.location}}</p>
</div>
</div>
</transition-group>
</div>
Data
data() {
return {
locations:['Sydney','Melbourne'],
types:['backpackers','hotel','resort'],
selectedLocations:[],
selectedTypes:[],
hotels:[
{name:'a Hotel',location:'Sydney', type:'backpackers'},
{name:'b Hotel',location:'Sydney', type:'hotel'},
{name:'c Hotel',location:'Sydney', type:'resort'},
{name:'d Hotel',location:'Melbourne',type:'hotel'},
{name:'e Hotel',location:'Melbourne', type:'resort'},
{name:'f Hotel',location:'Melbourne', type:'hotel'},
]
}
},
Computed
computed:{
filteredHotels(){
if(this.selectedLocations.length){
return this.hotels.filter(j => this.selectedLocations.includes(j.location))
}
else if(this.selectedTypes.length){
return this.hotels.filter(j => this.selectedTypes.includes(j.type))
}
else{
return this.hotels;
}
}
}
Fiddle
Pass your data via binding this or using ()=>, e.g:
filteredHotels(){
return this.hotels.filter(function (el) {
return this.selectedLocations.includes(el.location)
|| this.selectedTypes.includes(el.type)
}.bind(this));
}
Fiddle
Here is a working example:
I've updated the condition under computed property as below: Include only location which is being selected. Instead of just returning the current selected location.
computed:{
filteredHotels(){
console.log(this.selectedLocations);
if(!this.selectedLocations.length) {
return this.hotels;
} else {
return this.hotels.filter(j => this.selectedLocations.includes(j.location))
}
}
}
new Vue({
el: "#app",
data: {
locations: ['Sydney', 'Melbourne'],
types: ['backpackers', 'hotel', 'resort'],
selectedLocations: [],
selectedTypes: [],
filtersAppied: [],
hotels: [{
name: 'a Hotel',
location: 'Sydney',
type: 'backpackers'
},
{
name: 'b Hotel',
location: 'Sydney',
type: 'hotel'
},
{
name: 'c Hotel',
location: 'Sydney',
type: 'resort'
},
{
name: 'd Hotel',
location: 'Melbourne',
type: 'hotel'
},
{
name: 'e Hotel',
location: 'Melbourne',
type: 'resort'
},
{
name: 'f Hotel',
location: 'Melbourne',
type: 'hotel'
},
]
},
methods: {
setActive(element) {
if (this.filtersAppied.indexOf(element) > -1) {
this.filtersAppied.pop(element)
} else {
this.filtersAppied.push(element)
}
},
isActive: function (menuItem) {
return this.filtersAppied.indexOf(menuItem) > -1
},
},
computed: {
filterApplied: function() {
if (this.filtersAppied.indexOf(element) > -1) {
this.filtersAppied.pop(element)
} else {
this.filtersAppied.push(element)
}
},
filteredHotels: function() {
return this.hotels.filter(hotel => {
return this.filtersAppied.every(applyFilter => {
if (hotel.location.includes(applyFilter)) {
return hotel.location.includes(applyFilter);
}
if (hotel.type.includes(applyFilter)) {
return hotel.type.includes(applyFilter);
}
});
});
}
}
})
body {
background: #20262E;
padding: 20px;
font-family: Helvetica;
}
#app {
background: #fff;
border-radius: 4px;
padding: 20px;
transition: all 0.2s;
}
li {
margin: 8px 0;
}
h2 {
font-weight: bold;
margin-bottom: 15px;
}
del {
color: rgba(0, 0, 0, 0.3);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<div>
<div class="row pt-5">
<div class="col">
{{filteredHotels}}
<h5>Locations</h5>
<label v-for="(value, key) in locations">
{{value}}
<input type="checkbox" :value="value" v-model="selectedLocations" :checked="isActive(value)" #click="setActive(value)">
</label> {{selectedLocations}}
</div>
</div>
<div class="row pt-5">
<div class="col">
<h5>Type</h5>
<label v-for="(value, key) in types">
{{value}}
<input type="checkbox" :value="value" v-model="selectedTypes"
:checked="isActive(value)"#click="setActive(value)">
</label> {{selectedTypes}}
</div>
</div>
<div class="row">
<div class="col-sm-3 pb-4" v-for="hotel in filteredHotels">
<div class="card text-center">
<h1>{{hotel.name}}</h1>
<p>{{hotel.location}}</p>
</div>
</div>
</div>
</div>
</div>
Hope this helps!