2

I am learning Vue and trying to complete a task myself.

I would like to find out how to run v-for loop on @click so that on initial state, only "city" template appears, and on each click, tour template renders with related tours.

let EventBus = new Vue();
Vue.component('cities', {

	name: 'Listings',
	props: ['city','tour'],
	
	template: `
	<div>
	<div class='city-list box'>
	<city v-for='city in cities' :id='city.id' :key='city.id' :city='city' :tour='tour' @click.native='select(city)'></city>
	</div>
	<div class='tour-list box'>
	<tours v-for='tour in filter(tours)' :id='tour.id' :key='tour.id' :tour='tour'></tours>
	</div>
	</div>
	`,

	data() {
		return {

			cities: [
			{id:1, name: 'Istanbul'},
			{id:2, name: 'Paris'},
			{id:3, name: 'Barça'},
			{id:4, name: 'Rome'},
			{id:5, name: 'Mars'}
			],

			tours: [
			{id:1, cid:1, name: 'Bosphorus'},
			{id:2, cid:2, name: 'Eiffel'},
			{id:3, cid:3, name: 'La Sagrada Familia'},
			{id:4, cid:4, name: 'Colosseum'},
			{id:5, cid:5, name: 'Mars Canyon'},
			{id:6, cid:1, name: 'Sultanahmet'},
			{id:7, cid:2, name: 'Champs-Élysées'},
			{id:8, cid:3, name: 'Casa Mila'},
			{id:9, cid:4, name: 'Trevi Fountain'},
			{id:10, cid:5, name: 'Mars Desert'},
			]
		};
	},

	methods: {
		select(city) {
			console.log('select');
			EventBus.$emit('filter', city);
		},

		filter(tours) {
			console.log('filter');
			EventBus.$on('select', ()=>{
			cid = this.city.id;
			return tours.filter(function(tour) {
				return tour.cid == cid;
			});
		});
		},
	},

	components: {

		'city': {
			name: 'City',
			props: ['city'],
			template: `
			<div :id="[city.name.toLowerCase()]" :class="[city.name.toLowerCase()]">
			<h1>{{ city.name }}</h1>
			</div>`
		},

		'tour': {
			name: 'Tour',
			props: ['city', 'tour'],
			template: `
			<div :class="['tour-' + tour.id]" :id="[city.name.toLowerCase() + '-tours']" :refs="city.id" :data-id="city.id">
			{{ tour.name }}
			</div>
			`,
		},
	},

});

new Vue({
	el: '#root'
});
	body {
		font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
	}
	.box {
		margin: 48px auto;
		max-width: 1024px;
		display: flex;
		justify-content: center;
		align-items: center;
	}
	.box h1 {
		font-size: 1.1rem;
		color: #41f;
	}
	.box > div {
		padding: 24px;
		margin: 12px;
		width: 20%;
		min-height: 100px;
		border-radius: 2px;
		font-size: 1.15rem;
		line-height: 1;
	}

	.box > div:nth-child(1)
	{background-color: #ffb3ba;}
	.box > div:nth-child(2)
	{background-color: #ffdfba;}
	.box > div:nth-child(3)
	{background-color: #ffffba;}
	.box > div:nth-child(4)
	{background-color: #baffc9;}
	.box > div:nth-child(5)
	{background-color: #bae1ff;}
<script src="https://unpkg.com/[email protected]/dist/vue.js"></script>
	<div id="root">
		<cities></cities>
	</div>

I am also interested in the state of art, if it is a good practice to have two templates together (which are related), and connect this model with a db and router (city/tour-list). Or how would you approach to a such case (I guess jsfiddle should be self explanatory).

As a side note I have tried adding tour as a child to parent component [jsfiddle] where I filter results by ID, I am not sure if this way is a better approach both for components and filtering results in the sense of architecture.

https://jsfiddle.net/oy5fdc0r/29/

1 Answer 1

2

https://jsfiddle.net/oy5fdc0r/30/

Use a data property to keep track of the selected city, instead of an Eventbus. Then you can use a computed property to show the correct tours, based on the selected city.

computed:{
      selectedTours(){
          return this.tours.filter(tour=>tour.cid == this.selectedCity.id)
      }
  },
    methods: {
        select(city) {
            this.selectedCity = city;
        },
    },
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.