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

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.

Related

Vue.js Axios: unable to update page after HTTP GET request

I'm quite new to Vue.js and Axios. I'd like to learn it to create A REST CRUD Interface.
Starting from the HTTP GET request, the examples I've found so far all execute an HTTP GET when the page load and print the returned data. That works pretty well.
On the other hand, I need to display the data when I click a button. Here's what I have coded so far:
<script>
new Vue({
el: "#app",
data() {
return {
users: []
}
},
})
</script>
<script>
function performGetRequest1() {
axios
.get('http://localhost:8080/users')
.then(response => {
this.users = response.data,
})
.catch(function (error) {
console.log(error);
})
}
</script>
<button onclick="performGetRequest1()">Get Todos</button>
<tr v-for="user in users" :key="user.id">
<td>{{user.id}}</td>
<td>{{user.name}}</td>
<td>{{user.surname}}</td>
</tr>
So, I can see that when I hit the button the function correctly invokes the backend and data is returned. However, even if I set the users array to the response that is not updated in the table.
I believe I should set my request to be ajax based, just my attempts so far have failed.
Any help?
I believe the issue here is that you are working in 2 different contexts: you create the Vue app in one context and then you write the Axios script in a totally different context. Vue is reactive and will update your HTML, but only with data that it knows about. Thus, you're very close, but you just need to move your Axios script into Vue's context! Your best bet is going to be turning performGetRequest1 into a Vue method.
Additionally, your "onclick" handler on the button is a Javascript handler and not something Vue is going to listen to. You should be using the v-on:click (or shorthand, #click) prop to listen for the click event.
Check out the "Handling User Input" section of the Vue docs: https://v2.vuejs.org/v2/guide/#Handling-User-Input
<script>
new Vue({
el: "#app",
methods: {
performGetRequest1() {
axios
.get('http://localhost:8080/users')
.then(response => {
this.users = response.data
})
.catch(function (error) {
console.log(error);
})
}
}
data() {
return {
users: []
}
},
})
</script>
<button #click="performGetRequest1">Get Todos</button>
<tr v-for="user in users" :key="user.id">
<td>{{user.id}}</td>
<td>{{user.name}}</td>
<td>{{user.surname}}</td>
</tr>
Your script tag where you define performGetRequest1 is not associated with your Vue instance, so the this in this.users = response.data is not pointing to the Vue instance. Instead, it's likely pointing to the global window object. You should put performGetRequest1 in the Vue instance's methods property:
new Vue({
el: '#app',
data () {
return {
users: []
}
},
// ADD THE CODE BELOW
methods: {
performGetRequest1 () {
// Load the data
}
}
}

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

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

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