0

This is the code I'm using to try creating a single page app. I'm reading about vue router and I've tried to apply it to my project. I'm not sure what's wrong with the code, but I'm not able to see the page where the app run. I get some errors on chrom console, but this happen after I've added vue router to my project. Any help to fix it?

<!doctype html> <html lang="en"> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"> <!-- Bootstrap CSS --> <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous"> <link rel="stylesheet" href="https://unpkg.com/[email protected]/dist/leaflet.css" integrity="sha512-xwE/Az9zrjBIphAcBb3F6JVqxf46+CDLwfLMHloNu6KEQCAWi6HcDUbeOfBIptF7tcCzusKFjFw2yuvEpDL9wQ==" crossorigin=""/> <link href="https://fonts.googleapis.com/css2?family=Courgette&display=swap" rel="stylesheet"> <script src="https://code.jquery.com/jquery-3.4.1.slim.min.js" integrity="sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n" crossorigin="anonymous"></script> <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/umd/popper.min.js" integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo" crossorigin="anonymous"></script> <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js" integrity="sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6" crossorigin="anonymous"></script> <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> <script src="https://unpkg.com/vue-router/dist/vue-router.js"></script> <script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script> <script src="https://unpkg.com/[email protected]/dist/leaflet.js" integrity="sha512-gZwIG9x3wUXg2hdXF6+rVkLF/0Vi9U8D2Ntg4Ga5I5BZpVkVxlJWbSQtXPSiUTtC0TjtGOmxa1AJPuV0CPthew==" crossorigin=""></script> <title>C safe!</title> </head> <body> <style> h1{ font-family: 'Courgette', cursive; } .list-group { max-height: 300px; margin-bottom: 10px; overflow:scroll; -webkit-overflow-scrolling: touch; } #map { height: 400px; } </style> <div class="container-fluid bg-light p-0" id="app"> <div class="row"> <div class="col-sm-12 col-md-12 col-lg-12 p-5"> <ul class="nav"> <router-link to="/"> <li class="nav-item"> <a class="nav-link" href="#">Home</a> </li> </router-link> </ul> </div> </div> <script type="text/x-template" id="search-bar"> <div class="row justify-content-center m-0" style="height:100vh;"> <div class="col-sm-12 col-md-8 col-lg-8 p-5 mx-auto"> <h1 class="mt-5 mb-3 text-center">C</h1> <div class="input-group"> <input type="email" class="form-control rounded-0" v-on:change="instantSearch()" v-model="q" placeholder="Cerca nelle vicinanze es: Pizzeria"> <div class="input-group-append"> <button class="btn btn-outline-success rounded-0" v-on:click="instantSearch()">Cerca</button> </div> </div> <ul v-if="resultSet" class="list-group rounded-0"> <small v-if="q" class="list-group-item rounded-0"><a class="text-muted" href="#" v-on:click="resetSearch()">Annulla</a></small> <router-link to="/results"> <a v-for="result in resultSet" :key="result.id" v-on:click="expandMap(result.lat, result.lon)" href="#" class="list-group-item rounded-0" :place="result.display_name">{{ result.display_name }}</a> </router-link> </ul> <ul class="nav"> <li class="nav-item"> <a class="nav-link" href="#">FAQ</a> </li> <li class="nav-item"> <a class="nav-link" href="#">Aggiungi la tua attività</a> </li> </ul> </div> </div> </script> <script type="text/x-template" id="result-detail"> <div class="collapse" id="map-collapsable"> <div class="row m-0 results-map"> <div class="col-sm-12 col-md-8 col-lg-8 p-0" id="map"></div> <div v-for="place in placeData" class="col-sm-12 col-md-4 col-lg-4"> {{ place.lat }} {{ place.lng }} </div> </div> </div> </script> <router-view></router-view> </div> <!-- TODO: Vue components --> <script src="app.js"></script> </body> </html> 

This is the JS vue code

window.onload = function(){ Vue.component('search-bar',{ template: '#search-bar', data(){ return {} } }); Vue.component('view-result',{ template: '#result-detail', data(){ return {} } }); const searchbar = {template: 'search-bar'} const result = {template: 'view-result'} const routes = [ {path: '/', component: searchbar}, {path: '/results', component: result} ]; const router = new VueRouter({ routes // short for `routes: routes` }); const web = new Vue({ router, el: '#app', data: { pageData: [], resultSet: [], placeData: [], q: '', name: '', }, mounted: function(){ //this.initPage(); }, ready: function(){ }, computed: { }, watch: { q: function(val, oldVal){ this.instantSearch(); } }, methods: { instantSearch: function(){ axios.get('https://nominatim.openstreetmap.org/search?q='+this.q+'&format=json').then( (places) => { console.log(places); this.resultSet = []; places.data.forEach( (item, i) => { this.resultSet.push(item); }); }); }, resetSearch: function(){ this.resultSet = []; this.q = ''; }, expandMap: function(lat, lng){ let collapsable = document.getElementById('map-collapsable'); console.log(lat, lng); //$(collapsable).collapse(); this.placeData.push({lat: lat, lng: lng}); }, initMap: function(data){ } } }).$mount('#app'); } 

The errors I get are the following:

vue.js:634 [Vue warn]: Property or method "result" is not defined on the instance but referenced during render. Make sure that this property is reactive, either in the data option, or for class-based components, by initializing the property. See: https://v2.vuejs.org/v2/guide/reactivity.html#Declaring-Reactive-Properties. (found in <Root>) warn @ vue.js:634 warnNonPresent @ vue.js:2047 has @ vue.js:2092 eval @ VM258:3 Vue._render @ vue.js:3551 updateComponent @ vue.js:4067 get @ vue.js:4478 Watcher @ vue.js:4467 mountComponent @ vue.js:4074 Vue.$mount @ vue.js:9044 Vue.$mount @ vue.js:11944 Vue._init @ vue.js:5012 Vue @ vue.js:5078 window.onload @ app.js:28 load (async) (anonymous) @ app.js:1 vue.js:634 [Vue warn]: Error in render: "TypeError: Cannot read property 'display_name' of undefined" (found in <Root>) warn @ vue.js:634 logError @ vue.js:1893 globalHandleError @ vue.js:1888 handleError @ vue.js:1848 Vue._render @ vue.js:3553 updateComponent @ vue.js:4067 get @ vue.js:4478 Watcher @ vue.js:4467 mountComponent @ vue.js:4074 Vue.$mount @ vue.js:9044 Vue.$mount @ vue.js:11944 Vue._init @ vue.js:5012 Vue @ vue.js:5078 window.onload @ app.js:28 load (async) (anonymous) @ app.js:1 vue.js:1897 TypeError: Cannot read property 'display_name' of undefined at Proxy.eval (eval at createFunction (vue.js:11649), <anonymous>:3:1557) at Vue._render (vue.js:3551) at Vue.updateComponent (vue.js:4067) at Watcher.get (vue.js:4478) at new Watcher (vue.js:4467) at mountComponent (vue.js:4074) at Vue.$mount (vue.js:9044) at Vue.$mount (vue.js:11944) at Vue._init (vue.js:5012) at new Vue (vue.js:5078) logError @ vue.js:1897 globalHandleError @ vue.js:1888 handleError @ vue.js:1848 Vue._render @ vue.js:3553 updateComponent @ vue.js:4067 get @ vue.js:4478 Watcher @ vue.js:4467 mountComponent @ vue.js:4074 Vue.$mount @ vue.js:9044 Vue.$mount @ vue.js:11944 Vue._init @ vue.js:5012 Vue @ vue.js:5078 window.onload @ app.js:28 load (async) (anonymous) @ app.js:1 vue.js:634 [Vue warn]: Cannot find element: #app warn @ vue.js:634 query @ vue.js:5666 Vue.$mount @ vue.js:11882 window.onload @ app.js:83 load (async) (anonymous) @ app.js:1 vue.js:634 [Vue warn]: Property or method "result" is not defined on the instance but referenced during render. Make sure that this property is reactive, either in the data option, or for class-based components, by initializing the property. See: https://v2.vuejs.org/v2/guide/reactivity.html#Declaring-Reactive-Properties. (found in <Root>) warn @ vue.js:634 warnNonPresent @ vue.js:2047 has @ vue.js:2092 eval @ VM258:3 Vue._render @ vue.js:3551 updateComponent @ vue.js:4067 get @ vue.js:4478 Watcher @ vue.js:4467 mountComponent @ vue.js:4074 Vue.$mount @ vue.js:9044 Vue.$mount @ vue.js:11944 window.onload @ app.js:83 load (async) (anonymous) @ app.js:1 vue.js:634 [Vue warn]: Error in render: "TypeError: Cannot read property 'display_name' of undefined" (found in <Root>) warn @ vue.js:634 logError @ vue.js:1893 globalHandleError @ vue.js:1888 handleError @ vue.js:1848 Vue._render @ vue.js:3553 updateComponent @ vue.js:4067 get @ vue.js:4478 Watcher @ vue.js:4467 mountComponent @ vue.js:4074 Vue.$mount @ vue.js:9044 Vue.$mount @ vue.js:11944 window.onload @ app.js:83 load (async) (anonymous) @ app.js:1 vue.js:1897 TypeError: Cannot read property 'display_name' of undefined at Proxy.eval (eval at createFunction (vue.js:11649), <anonymous>:3:1557) at Vue._render (vue.js:3551) at Vue.updateComponent (vue.js:4067) at Watcher.get (vue.js:4478) at new Watcher (vue.js:4467) at mountComponent (vue.js:4074) at Vue.$mount (vue.js:9044) at Vue.$mount (vue.js:11944) at window.onload (app.js:83) logError @ vue.js:1897 globalHandleError @ vue.js:1888 handleError @ vue.js:1848 Vue._render @ vue.js:3553 updateComponent @ vue.js:4067 get @ vue.js:4478 Watcher @ vue.js:4467 mountComponent @ vue.js:4074 Vue.$mount @ vue.js:9044 Vue.$mount @ vue.js:11944 window.onload @ app.js:83 load (async) (anonymous) @ app.js:1 

I don't know why but before I create the components and try to use the vue-router, all was working fine.

1 Answer 1

2

There are a few problems:

  1. The script type=text/x-templates need to be moved outside of the app div. Otherwise, the template would be processed as part of the app's template, resulting in the undefined errors you observed in the console.

  2. Since your Vue declaration already specifies el: #app, you need to remove .$mount('#app').

  3. The route paths incorrectly specify a literal string template in: { template: 'search-bar' } and { template: 'result-detail' }. That should be { template: '<search-bar />' } and { template: '<result-detail />' } respectively.

  4. The q and resultSet data props should be moved into the search-bar component. Similarly, the placeData data prop should be moved into the result-detail component.

Demo:

window.onload = function(){ Vue.component('search-bar',{ template: '#search-bar', data(){ return { resultSet: [], q: '', } } }); Vue.component('view-result',{ template: '#result-detail', data(){ return { placeData: [], } } }); const searchbar = {template: '<search-bar />'} const result = {template: '<view-result />'} const routes = [ {path: '/', component: searchbar}, {path: '/results', component: result} ]; const router = new VueRouter({ routes // short for `routes: routes` }); const web = new Vue({ router, el: '#app', data: { pageData: [], name: '', }, mounted: function(){ //this.initPage(); }, ready: function(){ }, computed: { }, watch: { q: function(val, oldVal){ this.instantSearch(); } }, methods: { instantSearch: function(){ axios.get('https://nominatim.openstreetmap.org/search?q='+this.q+'&format=json').then( (places) => { console.log(places); this.resultSet = []; places.data.forEach( (item, i) => { this.resultSet.push(item); }); }); }, resetSearch: function(){ this.resultSet = []; this.q = ''; }, expandMap: function(lat, lng){ let collapsable = document.getElementById('map-collapsable'); console.log(lat, lng); //$(collapsable).collapse(); this.placeData.push({lat: lat, lng: lng}); }, initMap: function(data){ } } }) }
<script src="https://unpkg.com/[email protected]/dist/vue.min.js"></script> <script src="https://unpkg.com/[email protected]/dist/vue-router.js"></script> <style> h1{ font-family: 'Courgette', cursive; } .list-group { max-height: 300px; margin-bottom: 10px; overflow:scroll; -webkit-overflow-scrolling: touch; } #map { height: 400px; } </style> <div class="container-fluid bg-light p-0" id="app"> <div class="row"> <div class="col-sm-12 col-md-12 col-lg-12 p-5"> <ul class="nav"> <router-link to="/"> <li class="nav-item"> <a class="nav-link" href="#">Home</a> </li> </router-link> </ul> </div> </div> <router-view></router-view> </div> <script type="text/x-template" id="search-bar"> <div class="row justify-content-center m-0" style="height:100vh;"> <div class="col-sm-12 col-md-8 col-lg-8 p-5 mx-auto"> <h1 class="mt-5 mb-3 text-center">C</h1> <div class="input-group"> <input type="email" class="form-control rounded-0" v-on:change="instantSearch()" v-model="q" placeholder="Cerca nelle vicinanze es: Pizzeria"> <div class="input-group-append"> <button class="btn btn-outline-success rounded-0" v-on:click="instantSearch()">Cerca</button> </div> </div> <ul v-if="resultSet" class="list-group rounded-0"> <small v-if="q" class="list-group-item rounded-0"><a class="text-muted" href="#" v-on:click="resetSearch()">Annulla</a></small> <router-link to="/results"> <a v-for="result in resultSet" :key="result.id" v-on:click="expandMap(result.lat, result.lon)" href="#" class="list-group-item rounded-0" :place="result.display_name">{{ result.display_name }}</a> </router-link> </ul> <ul class="nav"> <li class="nav-item"> <a class="nav-link" href="#">FAQ</a> </li> <li class="nav-item"> <a class="nav-link" href="#">Aggiungi la tua attività</a> </li> </ul> </div> </div> </script> <script type="text/x-template" id="result-detail"> <div class="collapse" id="map-collapsable"> <div class="row m-0 results-map"> <div class="col-sm-12 col-md-8 col-lg-8 p-0" id="map"></div> <div v-for="place in placeData" class="col-sm-12 col-md-4 col-lg-4"> {{ place.lat }} {{ place.lng }} </div> </div> </div> </script>

Sign up to request clarification or add additional context in comments.

3 Comments

Thanks for the help. I'm new to vue so I make a lot of mistakes at the moment. From the main instance of vue, is there something I can pass to the components? I need to use the <router-link> function to change the view at click on instant search result
In particular, the details of a search result needs to be passed to the result component, some help will be appreciated
@guggio There are a few ways to handle this. You could implement v-model in search-bar and a public prop in view-result. In app, bind the two together with a local data prop. I recommend asking that as a new question to get more helpful answers.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.