Vue.js don't work with external JSON in HTML file - javascript

I want to get data from external JSON file for one var. I think the problem is what I using in-html vue.js and Vue.js don't understand what I wrote for him:joy:
jsfiddle
And the second problem is what I can't use value from json:
new Vue({
el: '#app',
data() {
return {
searchResult: [],
search: '',
}
},
created: function() {
this.searchResult = [
{
"id": 0,
"title": "d",
"img": "src"
}
];
},
computed: {
filteredName: function() {
return this.searchResult.filter((x) => {
return x.title.match(this.search)
});
},
allOK: function () {
if (this.search.valueOf() === "") {
return false
} else {
return true
}
},
hrefResult: function () {
return "/item?=" + this.searchResult.id
}
}
});
What I'm gonna do? :(

The problem is you're using ECMAScript Imports outside of a module script. The import keyword is only recognized inside <script type="module">, so your usage would result in a syntax error: Unexpected identifier on the line of your import statement (where you try to import json/products.json).
There are a couple solutions that require a modern browser (and polyfills for older browsers).
OPTION 1: Change your script to include type="module", and make sure to use relative paths in the import path. demo
<!-- inside HTML file -->
<script type="module">
import products from './json/products.json.js'
new Vue({
el: '#app',
data () {
return {
items: products
}
}
})
</script>
OPTION 2: Fetch the external JSON file instead of importing it. demo
<!-- inside HTML file -->
<script>
(async () => {
const productsResponse = await fetch('./json/products.json');
const products = await productsResponse.json();
new Vue({
el: '#app',
data () {
return {
items: products
}
}
})
})();
</script>
Alternatively, you could switch to vue-cli projects, which includes transpiling in its build, allowing you to use imports for external JSON files. demo

Related

Problem with vue-google-oauth-2 in Vue.js

I am trying to add a Google Sign-In button to my Vue.js application and I found the vue-google-oauth2 plugin. I installed it and followed exactly the sample.html code to integrate it in my application, this way:
<template>
<div>
<h1>Test</h1>
<button #click="handleClickSignIn" :disabled="!isLoaded">signIn</button>
</div>
</template>
<script>
/**
* You should first need to place these 2 lines of code in your APP ENTRY file, e.g. src/main.js
*
* import GAuth from 'vue-google-oauth2'
* Vue.use(GAuth, {clientId: '4584XXXXXXXX-2gqknkvdjfkdfkvb8uja2k65sldsms7qo9.apps.googleusercontent.com'})
*
*/
export default {
name: 'test',
props: [],
components: {
},
data () {
return {
isLoaded: false
}
},
computed: {
},
methods: {
handleClickSignIn(){
this.$gAuth.signIn(function (user) {
//on success do something
console.log('user', user)
}, function (error) {
//on fail do something
})
}
},
mounted(){
let that = this
let checkGauthLoad = setInterval(function(){
that.isLoaded = that.$gAuth.isLoaded()
console.log('checked', that.isLoaded)
if(that.isLoaded) clearInterval(checkGauthLoad)
}, 1000);
}
}
</script>
The problem is that the isLoaded() method never returns true, with the Google Chrome console telling me every time I press on the button that the google api is not ready, that is the plugin console message printed when the GoogleAuthInstance is false. Could anyone help me?
Use isInit instead of isLoaded as the latter will be/is deprecated.
Add to main.js
import GAuth from 'vue-google-oauth2'
Vue.use(GAuth, {
clientId: '....apps.googleusercontent.com',
scope: 'email',
prompt: 'consent',
fetch_basic_profile: true
})
new Vue({
...
render: (h) => h(App),
}).$mount("#app");

vue.js render ajax data that contains vue.js syntax

Vue.js version is: 2.x
Hi. I'm sending an ajax request in vue js to another page and getting it's source which contains vue.js syntax such as events. When this source is added to property and property added to a template, the ajax data source (that contains vue.js syntax) can not be rendered and does not work properly.
For example template is:
<div id="app">
{{{ foo }}}
</div>
and app.js is:
var app = new Vue({
el: '#app',
data: {
foo: 'bar'
},
mounted(){
this.$http.get('/media').then(function(response){
data = response.body;
Vue.set(app, 'foo', data);
});
},
methods: {
alertVideoLink: function(event){
alert(event.target.href);
}
}
});
In the above app.js code, ajax request returns this code (that is response.body):
Video Link
but this link can't be rendered and does not work properly! I'm testing the render method and some useful hints, but no way found. Please help... Thanks
Sounds like you want to use an Async Component.
Something like...
components: {
'async-media': () => Vue.http.get('/media').then(res => ({
template: res.body,
methods: {
alertVideoLink (event) {
this.$emit('click', event)
}
}
}))
}
Then in your template...
<async-media #click="handleClickEventFromChildComponent" />
Here's an example using a timeout to fake "load" a template
var app = new Vue({
el: '#app',
data: {},
components: {
'async-media': () => new Promise(resolve => {
setTimeout(() => {
resolve({
template: 'Video Link',
methods: {
alertVideoLink(event) {
this.$emit('click', event.target.href)
}
}
})
}, 2000)
})
},
methods: {
handleClickEventFromChildComponent (href) {
console.info('Clicked on', href)
}
}
});
<div id="app">
<p>Wait 2 seconds</p>
<async-media #click="handleClickEventFromChildComponent" />
</div>
<script src="https://unpkg.com/vue#2.4.2/dist/vue.min.js"></script>
#Phil's answer is correct but in my project need to be changed. in this case, the better way is: using global components vs local components because is simple for this work.

How to get the latest data from parent to child components after page refresh

I am working on a project and using Vue.js for the frontend. I have following code in the main.js file.
new Vue({ // eslint-disable-line no-new
//el: '#app',
router,
data () {
return {
friends: []
}
},
methods: {
getFriends: function () {
return this.friends;
}
},
created: function () {
this.$http.get('/user/' + this.getUserIDCookie('userID') +
'/friends').then(function (response) {
this.friends = response.data;
});
},
components: {
'nav-bar': require('./components/Navigation.vue')
},
template: `
<div id="app">
<nav-bar></nav-bar>
<router-view class="router-view"></router-view>
</div>`
}).$mount('#app');
In one of the pages(for ex. when the page is redirected to localhost/#/user/1/details, I am retrieving the friends' list from main.js like below:
<script type="text/babel">
export default {
name: 'profile',
data: function () {
return {
user: {},
friends: []
}
},
methods: {
// Some methods
},
created: function () {
this.friends = this.$root.getFriends();
}
}
</script>
The problem arises when I refresh the current page. After page refresh, this.friends is null/undefined because this.$root.getFriends() is returning null/undefined. I can move it to user component, but I want to keep it in main.js so that GET call is used once and data will be available to the whole application.
Any input regarding how to solve this issue would be great. I am using Vue 2.0.1
Really, what you want to do, is pass the data the component needs as props.
The dirt simple easiest way to do it is this.
<router-view class="router-view" :friends="friends"></router-view>
And in your profile component,
export default {
props:["friends"],
name: 'profile',
data: function () {
return {
user: {},
friends: []
}
},
methods: {
// Some methods
}
}
If you want to get more sophisticated, the later versions of VueRouter allow you to pass properties to routes in several ways.
Finally, there's always Vuex or some other state management tool if your application gets complex enough.
The problem is that when you refresh the page, the whole app reloads, which includes the get, which is asynchronous. The router figures out that it needs to render details, so that component loads, and calls getFriends, but the asynchronous get hasn't finished.
You could work around this by saving and pulling the Promise from the get, but Bert's answer is correct: the Vue Way is to send data as props, not to have children pull it from parents.

Vue JS v-for not iterating over array

Hi guys I am using Vue JS to try and loop through my data. Here is my whole JS file:
var contentful = require('contentful');
var client = contentful.createClient({
space: 'HIDDEN',
accessToken: 'HIDDEN'
});
Vue.component('careers', {
template: '<div><div v-for="career in careerData">{{ fields.jobDescription }}</div></div>',
data: function() {
return {
careerData: []
}
},
created: function() {
this.fetchData();
},
methods: {
fetchData: function() {
client.getEntries()
.then(function (entries) {
// log the title for all the entries that have it
entries.items.forEach(function (entry) {
if(entry.fields.jobTitle) {
this.careerData = entries.items;
}
})
});
}
}
});
var app = new Vue({
el: '#app'
});
I am using methods to access some data from Contentful, once it has grabbed the necessary data it is sent to my data object.
If I console.log(careerData); within my console the following data is returned:
So I'd expect if I used v-for within my template and tried iterating over careerData it would render correctly however on my front-end I am left with an empty div like so:
<div id="app"><div></div></div>
I am currently pulling my component into my HTML like so:
<div id="app">
<careers></careers>
</div>
No errors are displayed within my console, can you think of any reason this might be happening?
Thanks, Nick
Several problems I think. As #dfsq said, you should use a arrow function if you want to keep context (this).
fetchData: function() {
client.getEntries()
.then(entries => {
this.careerData = entries.items
});
}
Then you may replace {{fields.jobDescription}} by {{career.fields.jobDescription}}, as #unholysheep wrote.
It may work. If it does not, you could add a this.$forceUpdate(); right after this.fetchData();
Use arrow function in forEach callback so you don't loose context:
fetchData: function() {
client.getEntries()
.then(entries => {
this.careerData = entries.items
});
}

Language in VueJS from JSON

I am trying to load locale language variables from a JSON Request (laravel generated) to VueJS since VueJS does not support locale out of the box. The ready function alert does not alert but the random text data variable does work. I know VueJS is loading correctly. There are no console errors and webpack compiles the vue. The lang array says empty and the lang.email shows blank. This is my issue. Any help appreciated.
const app = new Vue({
el: '#app',
data: {
lang: [],
randomtext: 'This is Random Text'
},
ready: function() {
alert('THIS DOES NOT ALERT');
this.getLanguage();
},
methods: {
getLanguage: function() {
this.$http.get('/lang/auth').then((response) => {
this.$set("lang", response)
}, (response) => {
alert(response);
});
}
}
});
the 'lang/auth'
{"email":"Email Address","password":"Password"}
my html:
<h5 class="content-group">#{{ randomtext }}</h5> // This Works
<input type="text" class="form-control" :placeholder="lang.email"> // This does not
Indeed, "ready" was deprecated in Vue.js 2
Try using "mounted" instead.
First, Change ready: into mounted:
(Because, vuejs version 2 doesn't support it anymore)
Second, Instead of using this.$set use this.lang = response
Here is the full code
https://jsfiddle.net/uqp7f4zL/

Categories