Language in VueJS from JSON - javascript

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/

Related

Vue.js - Watch changes in JSON file

Here idea is to watch changes made in JSON file and if some value is changed it automatically changes the condition v-if.
<div id="app">
<div v-if="content == 'one'">
<p>Content one</p>
</div>
<div v-else-if="content == 'two'">
<p>Contentn two</p>
</div>
</div>
Now the tricky part comes, I need to be able after build to change the JSON file, and automatically to change what will be shown.
new Vue({
el: "#app",
data: {
content: ''
},
methods: {
// import of JSON and value that will assign value to this.content
// Now value can be 'one' or 'two'
}
})
Its not possible to watch for changes inside a json file.
What you could do is set the json to a reactive property and check for changes on there.
When changing the JSON you also need to update the reactive property so the watcher gets triggered
new Vue({
el: "#app",
data: {
content: ''
},
watch: {
content: function (val) {
// do something when content has changed
},
},
methods: {
importJson() {
// import json and set contents to content
},
saveJson(newJSON) {
this.content = newJSON
// Somehow save the json data to the json file
}
}
})
You should now that changes to a JSON file are not persistent.
I solve this issue with axios. :)
methods: {
updateData () {
axios.get('../static/client/data.json').then(response => {
console.log(response.data)
this.dataClient = response.data
})
}
},
created () {
this.updateData()
}
Now when you change JSON file in 'dist' folder after build and refresh browser it will load new value.

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 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.

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
});
}

How to call a vue.js function on page load

I have a function that helps filter data. I am using v-on:change when a user changes the selection but I also need the function to be called even before the user selects the data. I have done the same with AngularJS previously using ng-init but I understand that there is no such a directive in vue.js
This is my function:
getUnits: function () {
var input = {block: this.block, floor: this.floor, unit_type: this.unit_type, status: this.status};
this.$http.post('/admin/units', input).then(function (response) {
console.log(response.data);
this.units = response.data;
}, function (response) {
console.log(response)
});
}
In the blade file I use blade forms to perform the filters:
<div class="large-2 columns">
{!! Form::select('floor', $floors,null, ['class'=>'form-control', 'placeholder'=>'All Floors', 'v-model'=>'floor', 'v-on:change'=>'getUnits()' ]) !!}
</div>
<div class="large-3 columns">
{!! Form::select('unit_type', $unit_types,null, ['class'=>'form-control', 'placeholder'=>'All Unit Types', 'v-model'=>'unit_type', 'v-on:change'=>'getUnits()' ]) !!}
</div>
This works fine when I select a specific item. Then if I click on all lets say all floors, it works. What I need is when the page is loaded, it calls the getUnits method which will perform the $http.post with empty input. In the backend I have handled the request in a way that if the input is empty it will give all the data.
How can I do this in vuejs2?
My Code: http://jsfiddle.net/q83bnLrx
You can call this function in the beforeMount section of a Vue component: like following:
// .....
methods: {
getUnits: function() { /* ... */ }
},
beforeMount() {
this.getUnits()
},
// ......
Working fiddle: https://jsfiddle.net/q83bnLrx/1/
There are different lifecycle hooks Vue provide:
I have listed few are :
beforeCreate: Called synchronously after the instance has just been initialized, before data observation and event/watcher setup.
created: Called synchronously after the instance is created. At this stage, the instance has finished processing the options which means the following have been set up: data observation, computed properties, methods, watch/event callbacks. However, the mounting phase has not been started, and the $el property will not be available yet.
beforeMount: Called right before the mounting begins: the render function is about to be called for the first time.
mounted: Called after the instance has just been mounted where el is replaced by the newly created vm.$el.
beforeUpdate: Called when the data changes, before the virtual DOM is re-rendered and patched.
updated: Called after a data change causes the virtual DOM to be re-rendered and patched.
You can have a look at complete list here.
You can choose which hook is most suitable to you and hook it to call you function like the sample code provided above.
You need to do something like this (If you want to call the method on page load):
new Vue({
// ...
methods:{
getUnits: function() {...}
},
created: function(){
this.getUnits()
}
});
you can also do this using mounted
https://v2.vuejs.org/v2/guide/migration.html#ready-replaced
....
methods:{
getUnits: function() {...}
},
mounted: function(){
this.$nextTick(this.getUnits)
}
....
Beware that when the mounted event is fired on a component, not all Vue components are replaced yet, so the DOM may not be final yet.
To really simulate the DOM onload event, i.e. to fire after the DOM is ready but before the page is drawn, use vm.$nextTick from inside mounted:
mounted: function () {
this.$nextTick(function () {
// Will be executed when the DOM is ready
})
}
If you get data in array you can do like below. It's worked for me
<template>
{{ id }}
</template>
<script>
import axios from "axios";
export default {
name: 'HelloWorld',
data () {
return {
id: "",
}
},
mounted() {
axios({ method: "GET", "url": "https://localhost:42/api/getdata" }).then(result => {
console.log(result.data[0].LoginId);
this.id = result.data[0].LoginId;
}, error => {
console.error(error);
});
},
</script>
methods: {
methodName() {
fetch("url").then(async(response) => {
if (response.status === 200) {
const data = await response.json();
this.xy = data.data;
console.log("Success load");
}
})
}
}
you can do it using created() method. it will fire once page fully loaded.
created:function(){
this.fillEditForm();
},

Categories